从零开发分布式数据库中间件 二、构建MyBatis的读写分离数据库中间件

  在上一节  从零开发分布式数据库中间件 一、读写分离的数据库中间件 中,我们讲了如何通过ThreadLocal来指定每次访问的数据源,并通过jdbc的连接方式来切换数据源,那么这一节我们使用我们常用的数据库持久层框架MyBatis来实现数据库读写分离。

一、数据源代理:

此类与上一节相似,即可以指定当前线程访问的数据源。

package com.happyheng.datasource;

/**
 * 数据源代理设置
 * Created by happyheng on 17/1/15.
 */
public class DataSourceProxy {

    private static ThreadLocal threadLocal = new ThreadLocal<>();

    public enum DataSourceEnum {
        MASTER,
        SLAVE
    }

    /**
     * 为当前线程设置数据源
     */
    public static void setDataSource(DataSourceEnum sourceEnum) {
        threadLocal.set(sourceEnum);
    }

    public static DataSourceEnum getDataSource() {
        return threadLocal.get();
    }

}

二、数据源Map:

  首先我们需要将我们的读写数据源都写入到配置文件中,并设置到继承了AbstractRoutingDataSource抽象类的子类中,接下来我们会讲解AbstractRoutingDataSource的作用:

    
        
        
        
        
    

    
        
        
        
        
    

    
        
        
        
        
    

    
        
        
            
                
                
                
            
        
        
    

    
        
        
    


二、AbstractRoutingDataSource数据源路由类:

  在MyBatis中,需从SqlSessionFactory中获取dao文件,而SqlSessionFactory即需要数据源,因为我们需要根据不同的情况来选定数据源,所以不能写死一个数据源,而是应该将数据源写入到AbstractRoutingDataSource中的map中,AbstractRoutingDataSource即能够根据不同的情况指定访问的数据源。

  还有需要注意的是,AbstractRoutingDataSource是一个抽象类,需要实现其determineCurrentLookupKey方法,来指定每次访问数据库的数据源。

下为继承了AbstractRoutingDataSource的OptionalDataSource类:

package com.happyheng.datasource;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**
 * Created by happyheng on 17/1/10.
 */
public class OptionalDataSource extends AbstractRoutingDataSource {

    // 数据源
    private String masterDataSource = "masterDataSource";
    private String[] slaveDataSource = {"slaveDataSource1", "slaveDataSource2"};

    @Override
    protected Object determineCurrentLookupKey() {


        DataSourceProxy.DataSourceEnum dataSourceEnum = DataSourceProxy.getDataSource();

        if (dataSourceEnum == DataSourceProxy.DataSourceEnum.SLAVE) {

            double random = Math.random();
            int randomIndex = (int)(random * slaveDataSource.length);

            System.out.println("访问的是从数据库" + (randomIndex + 1));
            return slaveDataSource[randomIndex];
        } else {

            System.out.println("访问的是主数据库");
            return masterDataSource;
        }
    }
}

  首先,我们将一主两从的数据源都写入到OptionalDataSource的map中,而每次MyBatis访问数据库时,都会调用此类的determineCurrentLookupKey()来获取数据源map中的key,从而得到对应的数据源。

  可以看出,当我们发现是访问从数据库时,使用随机法来获取从数据库数据源,当发现是访问主数据库时,直接访问主数据库数据源。


4、此项目已在github上开源,可以完整实现MyBatis的数据库读写分离,地址为:github。如果觉得不错,那么就star一下来鼓励我吧。 



你可能感兴趣的:(中间件)