读写分离------基于spring和mybatis插件

前言

上一章介绍了MySQL主从同步,实现了双击热备,这里给大家介绍一下通过代码去实现读写分离。

读写分离

什么事读写分离?为什么读写分离?等等问题,我就不去介绍了有大神已经整理分析很好了,大家可以看一下这篇文章(很短)对读写分离有个大致的理解

【mysql 读写分离】10分钟了解读写分离的作用

分析

我们介绍的就是读写分离的第一种方式:基于程序代码内部实现。项目框架为SSM框架的一个web项目,如何搭建看这篇文章,上一篇中从同步配置了两个数据库,我们将为每个库定义一个数据源,分别为master,slave,增删改、有事务的操作在主库master,查询在从库slave。

综上,需求就是:根据数据库操作的类型去动态的修改要执行的数据源。

需求搞清楚之后,自然将会有下面两个问题

1. 如何切换数据源

我们在spring-jdbc.jar下找到一个AbstractRoutingDataSource类

//此类是一个抽象类,省略其他代码,看咱们关心的两行代码
public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean {
   
    //存放要动态切换的数据源
    private Map<Object, Object> targetDataSources;
    //每次操作数据库都会调用此方法,根据返回值动态选择数据源
    //抽象方法,定义当前使用的数据源(返回值为动态数据源的key值)
    protected abstract Object determineCurrentLookupKey();
}

由上面的类便知,我们只要把我们的数据源放到targetDataSources里,继承了AbstractRoutingDataSource 类,实现determineCurrentLookupKey方法,在增删改时让其返回master数据源的key,查询时slave数据源的key即可。

2. 如何判断即将执行的SQL是增,还是删,还是改,还是查?以便去修改数据源

有深入学习过Mybatis的肯定就可以想到,就是去编写一个Mybatis插件,拦截每一个数据库操作,根据条件判断哪个是增删改查。

可以看我的关于Mybatis的文章


通过上面的分析,我们总结一下我们要做的步骤

  1. AbstractRoutingDataSource 实现类,实现determineCurrentLookupKey方法
  2. 加载两个数据源(master,slave)将他们配置进AbstractRoutingDataSource的实现类
  3. 编写Mybatis插件去判断应该使用的数据源

上面有了步骤,我们按照步骤编写的过程中一定会发生很多问题,就像唐僧取经,去西天的路上你一定会遇到九九八十一难,但是你只要有了方向(西天),剩下的去克服了困难就一定能上西天,如果你没有方向,经历一万次劫难也到不了西天,思路永远比实现更加重要。

步骤

这里先进行一主一从架构的实现

1. AbstractRoutingDataSource 实现类,实现determineCurrentLookupKey方法

首先创建一个DynamicDataSourceHolder类去持有动态数据源的KEY

package com.csdn.shop.dao.split;


/**
 * 动态数据源类持有者,线程安全
 * 持有动态数据源的信息,以及修改清理数据源
 */
public class DynamicDataSourceHolder {
   
    //线程安全
    private static ThreadLocal<String> contextHolder = new ThreadLocal<String>();
    public static final String DB_MASTER = "master";
    public static final String DB_SLAVE = "slave";


    /**
     * 0
     * 获取线程的dbType
     *
     * @return
     */
    public static String getDbType() {
        String db = contextHolder.get();
        if (db == null)
            db = DB_MASTER;
        System.out.println("所使用的数据源为:" + db);
        return db;
    }

    /**
     * 设置线程的dbType
     *
     * @param datasource 数据源类型
     */
    public static void setDbType(String datasource) {

        contextHolder.set(datasource);
    }

    
  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值