java操作主从的2种方式

  • 1. 背景
    我们一般应用对数据库而言都是“读多写少”,也就说对数据库读取数据的压力比较大,有一个思路就是说采用数据库集群的方案,
    其中一个是主库,负责写入数据,我们称之为:写库;
    其它都是从库,负责读取数据,我们称之为:读库;

    那么,对我们的要求是:
    1、 读库和写库的数据一致;
    2、 写数据必须写到写库;
    3、 读数据必须到读库;
    2. 方案
    解决读写分离的方案有两种:应用层解决和中间件解决。

    2.1. 应用层解决:


    优点:
    1、 多数据源切换方便,由程序自动完成;
    2、 不需要引入中间件;
    3、 理论上支持任何数据库;
    缺点:
    1、 由程序员完成,运维参与不到;
    2、 不能做到动态增加数据源;

    2.2. 中间件解决

    优缺点:

    优点:
    1、 源程序不需要做任何改动就可以实现读写分离;
    2、 动态添加数据源不需要重启程序;

    缺点:
    1、 程序依赖于中间件,会导致切换数据库变得困难;
    2、 由中间件做了中转代理,性能有所下降;

    相关中间件产品使用:
    3. 使用Spring基于应用层实现3.1. 原理

    在进入Service之前,使用AOP来做出判断,是使用写库还是读库,判断依据可以根据方法名判断,比如说以query、find、get等开头的就走读库,其他的走写库。
    3.2. DynamicDataSource
    import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

    /**
    * 定义动态数据源,实现通过集成spring提供的AbstractRoutingDataSource,只需要实现determineCurrentLookupKey方法即可
    *
    * 由于DynamicDataSource是单例的,线程不安全的,所以采用ThreadLocal保证线程安全,由DynamicDataSourceHolder完成。
    *
    * @author zhijun
    *
    */
    public class DynamicDataSource extends AbstractRoutingDataSource{

        @Override
        protected Object determineCurrentLookupKey() {
            // 使用DynamicDataSourceHolder保证线程安全,并且得到当前线程中的数据源key
            return DynamicDataSourceHolder.getDataSourceKey();
        }

    }
    3.3. DynamicDataSourceHolder
    /**
    *
    * 使用ThreadLocal技术来记录当前线程中的数据源的key
    *
    * @author zhijun
    *
    */
    public class DynamicDataSourceHolder {

        //写库对应的数据源key
        private static final String MASTER = "master";

        //读库对应的数据源key
        private static final String SLAVE = "slave";

        //使用ThreadLocal记录当前线程的数据源key
        private static final ThreadLocal<String> holder = new ThreadLocal<String>();

        /**
         * 设置数据源key
         * @param key
         */
        public static void putDataSourceKey(String key) {
            holder.set(key);
        }

        /**
         * 获取数据源key
         * @return
         */
        public static String getDataSourceKey() {
            return holder.get();
        }

        /**
         * 标记写库
         */
        public static void markMaster(){
            putDataSourceKey(MASTER);
        }

        /**
         * 标记读库
         */
        public static void markSlave(){
            putDataSourceKey(SLAVE);
        }

    }
    3.4. DataSourceAspect
    import org.apache.commons.lang3.StringUtils;
    import org.aspectj.lang.JoinPoint;
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值