zoukankan      html  css  js  c++  java
  • spring MVC、mybatis配置读写分离,ReplicationDriver(转载)

    环境:

       3台数据库机器,一个master,二台slave,分别为slave1,slave2

        

    2.要实现的目标:

       ①使数据写入到master

       ②读数据时,从slave1和slave2中读取

        以此来实现数据库的读写分离

    3.原理:

       使用mysql驱动自带的replicationDriver来实现,replicationDriver简单来说就是存在两个Connection,一个masterConnection,一个slaveConnection;

       当setReadonly(true)就把currentConnection=slaveConnection,反之设置为masterConnection

    4.实现步骤:

    ①jdbc.properties

    1. ## 使用ReplicationDriver而不是driver  
    2. jdbc.driverClassName=com.mysql.jdbc.ReplicationDriver   
    3. ## 使用的是jdbc:mysql:replication://  
    4. jdbc.url=jdbc:mysql:replication://master:3306,slave1:3306,slave2:3306/test2?characterEncoding=utf8   
    5. jdbc.username=root  
    6. jdbc.password=123456  

    ②使用spring的事物,把读操作设置为readonly=true

    jdbc.connection.driver=com.mysql.jdbc.ReplicationDriver
    jdbc.connection.url=jdbc:mysql:replication://192.168.202.190,192.168.202.190/job?useUnicode=true&characterEncoding=utf-8
    1. <!-- 配置dataSource -->  
    2.   <bean class="com.alibaba.druid.pool.DruidDataSource"  
    3.         id="dataSource">  
    4.         <property name="driverClassName" value="${jdbc.driverClassName}"/>  
    5.         <property name="username" value="${jdbc.username}"/>  
    6.         <property name="password" value="${jdbc.password}"/>  
    7.         <property name="url" value="${jdbc.url}"></property>  
    8.   </bean>   
    9.     
    10.   <!-- transaction configuration-->  
    11.    <bean id="transactionManager"  
    12.     class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
    13.     <property name="dataSource" ref="dataSource" />  
    14.   </bean>   
    15.     
    16.   <!-- 定义事务通知 -->    
    17.     <tx:advice id="txAdvice" transaction-manager="transactionManager">    
    18.         <!-- 定义方法的过滤规则 -->    
    19.         <tx:attributes>    
    20.             <!-- 所有方法都使用事务 -->    
    21.             <tx:method name="*" propagation="REQUIRED"/>    
    22.             <!-- 定义所有get开头的方法都是只读的 -->    
    23.             <tx:method name="get*" read-only="true"/>    
    24.         </tx:attributes>    
    25.     </tx:advice>    
    26.         
    27.     <!-- 定义AOP配置 -->    
    28.     <aop:config>    
    29.         <!-- 定义一个切入点 -->    
    30.         <aop:pointcut expression="execution (* com.most.service.*.*(..))" id="services"/>    
    31.         <!-- 对切入点和事务的通知,进行适配 -->    
    32.         <aop:advisor advice-ref="txAdvice" pointcut-ref="services"/>    
    33.     </aop:config>    
    34.     
    35.   <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
    36.     <property name="dataSource" ref="dataSource" />  
    37.     <property name="configLocation" value="/WEB-INF/conf/mybatis-config.xml" />  
    38.   </bean>  


    所有以get开头的方法被调用时,readonly = true

    ps:这个只是实现了读写分离,master与slave之间的数据同步使用mysql replication即可

    昨晚看了一晚上的MySQL文档,主要是关于MySQL的复制方面的文档,用的工具是MySQL的帮助文档+金山词霸。

    终于比较大概的了解了如何通过复制来提升MySQL数据库的高可用性和处理能力,不过还没有经过实际的试验,但整体的思想是清楚了,下面把思路大概的描述一下,有机会再进行实验。

    首先在服务器端采用1+N的模型来安装和配置MySQL数据库。1就是一个master数据库,N就是一至多个slave数据库。master数据 库必须启用binlog模式,关于这两种数据库的配置参见MySQL的文档。配置完成后就形成了一个1+N的复制集群,当对master进行修改时会自动 把修改的数据更新到N个slave数据库上。但是有一个注意的是,所有的修改操作包括添加、删除、修改等语句必须作用在master数据库上,这样才能使 数据可靠的复制到其他slave服务器上。另外,由于slave服务器只用作查询,因此选用MyISAM的存储引擎可以提高查询的速度。

    而在客户端呢?如何使客户端程序能均衡的使用这些可用的服务器呢?而且更新操作只能对master进行处理。这个岂不是应用程序对数据库的操作逻辑非常的复杂?

    其实没有那么复杂,MySQL为我们提供了接口可以将这些复杂的操作透明化。ccccc下面主要介绍采用JDBC的客户端如何工作在基于复制的集群环境中,其他编程语言请参照mysql的文档。

    MySQL最新的JDBC驱动程序包中提供了一个驱动类就是 com.mysql.jdbc.ReplicationDriver 。这个驱动类允许在url中设置多个mysql主机地址,例如:

    jdbc:mysql://master1,slave1,slave2/dlog?autoReconnect=true&roundRobinLoadBalance=true

    在上面的url中,有三个主机地址分别是master1,slave1,slave2,其中ReplicationDriver 规定第一个主机是master主机地址,剩下的全部是slave主机。另外有两个参数必须指定为true,就是autoReconnect和roundRobinLoadBalance。

    使用这个驱动和配置后还不能马上解决所有的问题,我们还需要对程序做一些小改动。

    我们必须告诉驱动程序,哪些语句的执行是作用在master数据库,而哪些语句的执行作用在slave数据库上。

    ReplicationDriver 是通过Connection对象的readOnly属性来判断该操作是否为更新操作。因此我们在执行一个sql语句的时候必须调用一下 setReadOnly告诉驱动程序当前执行的操作是否是只读。如果你是使用hibernate操作数据库的,那可以调用 Query.setReadOnly方法。

    以上就是整个思路的大概描述,猜想肯定还有存在一些问题,例如因为数据的复制过程是异步的,也是说有可能执行了某个更新操作,但是查询的时候查不到的情况出现。当然这些问题只能在实际的过程中进行解决。

  • 相关阅读:
    es5预览本地文件、es6练习代码演示案例
    Java实现 LeetCode 838 推多米诺(暴力模拟)
    Java实现 LeetCode 838 推多米诺(暴力模拟)
    Java实现 LeetCode 838 推多米诺(暴力模拟)
    Java实现 LeetCode 837 新21点(DP)
    Java实现 LeetCode 837 新21点(DP)
    Java实现 LeetCode 837 新21点(DP)
    Java实现 LeetCode 836 矩形重叠(暴力)
    Subversion under Linux [Reprint]
    Subversion how[Reprint]
  • 原文地址:https://www.cnblogs.com/moxiaotao/p/10490072.html
Copyright © 2011-2022 走看看