您的位置:首页 > 编程语言 > Java开发

spring读写分离(mysql主从复制<3>)

2017-09-20 20:55 393 查看

一.读写分离原理:

 上一篇文章我们已经讲解了mysql主从复制的原理并且实现了   只要往主服务器中插入数据  那么从数据库slaver将会跟着同步主服务器master的数据

 那么我们java 代码来实现的话  只要动态切换数据库 就达到了读写分离的目的。本文中是用spring + mybatis 来整合案例的  那么我们如果能够做到动态
 的切换spring的数据源 从而就可以达到切换数据库的目的
 demo下载地址

二.spring实现切换数据库原理:

     通过Spring的AOP思想来实现   根据你访问的service方法名来判断此方法执行查询还是执行更改操作
     一般查询切换到从数据源    更改插入删除操作在主数据库   因为主数据库会同步到从数据库
    

     此时我们spring-mybatis.xml 文件中至少应该有两个数据源 masterDataSource  和slaverDataSource  稍后贴出 

     masterDataSource数据源配置 和我们普通的配置没什么差别(数据库信息从配置文件读取)
    
     <!-- 主库 用来写数据 -->
<bean id="dataSourceWriter" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
<!-- 初始化连接大小 -->
<property name="initialSize" value="${initialSize}"></property>
<!-- 连接池最大数量 -->
<property name="maxActive" value="${maxActive}"></property>
<!-- 连接池最大空闲 -->
<property name="maxIdle" value="${maxIdle}"></property>
<!-- 连接池最小空闲 -->
<property name="minIdle" value="${minIdle}"></property>
<!-- 获取连接最大等待时间 -->
<property name="maxWait" value="${maxWait}"></property>
</bean>

     slaverDataSource  数据源 
      <!-- 从库用来读数据 -->
<bean id="dataSourceReader" class="org.apach
4000
e.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${slaver.driver}" />
<property name="url" value="${slaver.url}" />
<property name="username" value="${slaver.username}" />
<property name="password" value="${slaver.password}" />
<!-- 初始化连接大小 -->
<property name="initialSize" value="${slaver.initialSize}"></property>
<!-- 连接池最大数量 -->
<property name="maxActive" value="${slaver.maxActive}"></property>
<!-- 连接池最大空闲 -->
<property name="maxIdle" value="${slaver.maxIdle}"></property>
<!-- 连接池最小空闲 -->
<property name="minIdle" value="${slaver.minIdle}"></property>
<!-- 获取连接最大等待时间 -->
<property name="maxWait" value="${slaver.maxWait}"></property>
</bean>

     我们原来sqlSessionFactory的bean中的属性dataSource 应该指向我们包含主数据源和从数据源的bean
     
     所以我们要定义一个dynamicDataSource 来管理masterDatas 和slaverDataSource   代码如下
     
   <!-- 动态数据源 -->  

   <bean id="dynamicDataSource" class="com.cn.wx.db.DynamicDataSource">  

       <!-- 通过key-value关联数据源 -->  

       <property name="targetDataSources">  

           <map>  

               <entry value-ref="dataSourceWriter" key="dataSourceWriter"></entry>  

               <entry value-ref="dataSourceReader" key="dataSourceReader"></entry>  

           </map>  

       </property>

       <!-- 默认的DataSource配置-->

       <property name="defaultTargetDataSource" ref="dataSourceWriter" />      

   </bean>

    此bean的class是我们自定义的class  需要集成 spring中的 AbstractRoutingDataSource重写一下方法
    
     @Override
protected Object determineCurrentLookupKey() {
// TODO Auto-generated method stub
return DBContextHolder.getDbType();
}  

DBContextHolder 类是我们自己定义的  用来返回与当前线程绑定的数据源的名称

核心代码如下:
/** 
* 线程threadlocal 
*/  

    private static ThreadLocal<String> contextHolder = new ThreadLocal<String>();  

  

    private static String DEFAUL_DB_TYPE_WRITER = "dataSourceWriter";   

    

    /* 获取本线程的dbtype

    * @return

    */

   public static String getDbType() {  

       String db = contextHolder.get();  

       if (db == null) {  

           db = DEFAUL_DB_TYPE_WRITER;// 默认是读写库  

       }  

       return db;  

    } 


3. spring AOP配置实现数据源切换:   

 我们访问以 select*  get* find* query* 开头的Service方法都会切换到读的数据源    直接上代码

   
  <!-- 数据源读写分离  aop -->

    <bean id="dynamicDataSourceAOP" class="com.cn.wx.db.DynamicDataSourceAOP">

        <property name="methods"> 

             <map>                  

                 <entry key="select*" value="dataSourceReader" />

                 <entry key="get*" value="dataSourceReader" />

                 <entry key="find*" value="dataSourceReader" />

                 <entry key="page*" value="dataSourceReader" />            

                 <entry key="query*" value="dataSourceReader" />

             </map>

           </property>

        <property name="defaultDataSource" value="dataSourceWriter"/>

     </bean>
      
     DynamicDataSourceAOP 是我们自己来根据service方法不同来切换数据源的核心逻辑 如下:

      


spring-mybatis.xml 中在原来的aop:config中加入AOP的切面如下:



至此其实我们的配置已经完毕 接下来就是测试读写分离是否成功。

4.测试读写分离配置是否成功:

接下我们来测试是否成功的实现了读写分离



我们插入往主数据库中插入一条数据    这个时候去查看从数据库 是否也有这条记录  有的话说明成功!

 

         继续验证读  是否从从数据库中读取的 代码如下:



,注意查询方法是AOP中拦截到的  数据源才会去切换到slaverDataSource  

此时主从数据库一样怎么验证查询的是从数据库呢   很简单 我们手动去修改从数据库的某一个字段值 除了按条件查询的值以外 都可以

此时我们主数据库数据如下:





从数据库数据如下:



修改从数据库的age 为28 此时主数据库还是原来的25 

如果查询的结果是28那么读写分离就已经实现了

现在执行查询方法



     sql语句打印的age是28  到此为止 就已经实现了读写分离

     demo下载地址


最后谢谢大家,大家觉得我写的可以 可以给我鼓励 打赏一下,多少都可以 哈哈哈

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: