zoukankan      html  css  js  c++  java
  • Mysql读写分离实例

    吐槽:前天刚加完MQ,这回加读写分离。我也是醉了,但是弄完之后,就发现,似乎没我想的那么复杂,真的!另外,昨天试了一下用swagger编写API文档,太方便了,加上Mock service测试。这两天都好忙啊,忙着优化项目,忙着写接口,不过,再忙的日子,也得写总结!今天,主要是记录一下,往项目中加读写分离的过程。

    1,mysql数据库安装,不说了。主从配置,也不说了。有需要的,请宝宝吃饭,宝宝手把手教!

    2,宏观描述一下过程:在访问service方法前,通过AOP做出判断(以方法名:嘿嘿,命名规范哈)如果是以query、find、get等读操作打头的,就走从库(读库),其他的,则走主库(写库)

    3、具体实施

    3.1,首先是定义动态数据源,通过继承实现Spring提供的AbstractRoutingDataSource抽象类的determineCurrentLookupKey方法:

    public class DynamicDataSource extends AbstractRoutingDataSource {
    
        /**
         * 定义动态数据源
         * @return
         */
        @Override
        protected Object determineCurrentLookupKey() {
            //返回当前线程中的数据源
            return DynamicDataSourceHolder.getDataSourceKey();
        }
    }
    public class DynamicDataSourceHolder {
    
        //写库数据源key值
        private static final String MASTER="master";
        //读库数据源key值
        private static final String SLAVE="slave";
    
        //使用threadlocal记录当前线程的数据源
        private static final ThreadLocal<String> holder=new ThreadLocal<>();
    
        //设置数据源
        public static void putDataSourceKey(String key){
            holder.set(key);
        }
    
        //获取数据源
        public static String getDataSourceKey(){
            return holder.get();
        }
    
        public static void markMaster(){
            putDataSourceKey(MASTER);
        }
    
        public static void markSlave(){
            putDataSourceKey(SLAVE);
        }
    }
    3.2,编写AOP织入的切面

    public class DataSourceAspect {
    
        /**
         * 进入service方法之前执行
         * @param joinpoint 切面对象
         */
        public void before(JoinPoint joinpoint){
            //获取当前执行方法名
            String methodName=joinpoint.getSignature().getName();
            //分别标记读、写库
            if(isSlave(methodName)){
                DynamicDataSourceHolder.markSlave();
            }else{
                DynamicDataSourceHolder.markMaster();
            }
        }
    
        /**
         * 是否是从库(读库)
         * @param methodName 访问的方法名称
         * @return 如果是从库,返回true
         */
        private boolean isSlave(String methodName){
            return StringUtils.startsWithAny(methodName,"query","find","get");
        }
    
    }

    3.3,配置数据源

    首先,是在db.properties文件中,配置两个数据源(可能会有多个从库,这里以主从分别为一个说明),分别为写库和读库

    其次,为两个数据源配置连接池

    然后,定义DataSource

    <bean id="dataSource" class="DynamicData.DynamicDataSource">
            <!--配置多个数据源-->
            <property name="targetDataSources">
                <map key-type="java.lang.String">
                    <entry key="master" value-ref="masterDataSource"/>
                    <entry key="slave" value-ref="slaveDataSource"/>
                </map>
            </property>
            <property name="defaultTargetDataSource" ref="masterDataSource"/>
    </bean>

    3.4,定义切面

    事务什么的,早就配好了,这里略过,主要是说关于读写分离的要点。

    <!--定义AOP切面处理器-->
        <bean class="DynamicData.DataSourceAspect" id="dataSourceAspect"/>
    
        <!-- 切面 -->
        <aop:config>
            <!-- 定义切面,所有的service的所有方法——读写 -->
            <aop:pointcut id="txPointcut"
                          expression="execution(* *.service.*.*(..))" />
    
            <!--事务传播策略-->
            <aop:advisor advice-ref="txAdvice"
                         pointcut="execution(* *.service.*.*(..))" />
            <!-- 将切面应用到自定义的切面处理器上,-9999保证该切面优先级最高执行 -->
            <aop:aspect ref="dataSourceAspect" order="-9999">
                <aop:before method="before" pointcut-ref="txPointcut" />
            </aop:aspect>
        </aop:config>

    4,总结

    这样子,就配好了(嘿嘿,但愿我没有忘记什么,这两天脑袋里东西有点多) 读写分离,配好了。值得一说的是,虽然没有过多的说mysql的安装配置,但是,对于主从的存储引擎配置,应该注意。分别为主从数据库,配置相应的存储引擎!



  • 相关阅读:
    YOLO V2 代码分析
    HDU 1728 逃离迷宫【BFS】
    POJ 2987 Firing【最大权闭合图-最小割】
    POJ 2914 Minimum Cut【最小割 Stoer-Wangner】
    模拟C#的事件处理和属性语法糖
    c版基于链表的插入排序(改进版)
    一句话概述代码的用途
    用python实现的抓取腾讯视频所有电影的爬虫
    jquery 实现智能炫酷的翻页相册效果
    KISSY(JS)炫动导航,缓动应用实例(^_^)
  • 原文地址:https://www.cnblogs.com/hhx626/p/7534580.html
Copyright © 2011-2022 走看看