应用层解决读写分离方案

介绍

解决数据库读写分离方案有,应用层解决数据库读写分离方案,中间件解决数据库读写分离两种方案。本文只介绍应用层解决读写分离方案。
在这里插入图片描述

第一种方案(推荐)
一 、查看AbstractRoutingDataSource类

首先查看一个spring的一个类AbstractRoutingDataSource,查看其属性,注意红框。
在这里插入图片描述

二、如何配置多数据源

再查看类中的其它方法:setTargetDataSources与afterPropertiesSet(InitializingBean接口的实现)。
setTargetDataSources方法给targetDataSources属性赋值。
在这里插入图片描述
afterPropertiesSet在setTargetDataSources赋值之后执行,给resolvedDataSources赋值。
在这里插入图片描述
所以我们如果要配置多个数据源我们就可以在spring配置文件中添加两个数据源,一个读一个写。

<!--配置数据库连接池读-->
    <bean id="dataSourceForRead" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <!--可不写,durid默认自动根据url识别-->
        <property name="driverClassName" value="${jdbc.read.driveClassName}" />
        <property name="url" value="${jdbc.read.url}" />
        <property name="username" value="${jdbc.read.username}" />
        <property name="password" value="${jdbc.read.password}" />

        <!--配置初始化大小,最小、最大-->
        <property name="initialSize" value="1" />
        <property name="minIdle" value="3" />
        <property name="maxActive" value="20" />

        <!--配置获取连接等待超时的时间-->
        <property name="maxWait" value="60000" />

        <!--配置间隔多久才进行以此检测,检测需要关闭的空闲连接,单位式毫秒-->
        <property name="timeBetweenEvictionRunsMillis" value="60000" />

        <!--配置一个连接在池中最小的生存时间,单位是毫秒-->
        <property name="minEvictableIdleTimeMillis" value="300000" />

        <!--配置监控统计拦截的filters-->
        <property name="filters" value="stat" />
    </bean>
    <!--配置数据库连接池写-->
    <bean id="dataSourceForWrite" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
        <!--可不写,durid默认自动根据url识别-->
        <property name="driverClassName" value="${jdbc.write.driveClassName}" />
        <property name="url" value="${jdbc.write.url}" />
        <property name="username" value="${jdbc.write.username}" />
        <property name="password" value="${jdbc.write.password}" />

        <!--配置初始化大小,最小、最大-->
        <property name="initialSize" value="1" />
        <property name="minIdle" value="3" />
        <property name="maxActive" value="20" />

        <!--配置获取连接等待超时的时间-->
        <property name="maxWait" value="60000" />

        <!--配置间隔多久才进行以此检测,检测需要关闭的空闲连接,单位式毫秒-->
        <property name="timeBetweenEvictionRunsMillis" value="60000" />

        <!--配置一个连接在池中最小的生存时间,单位是毫秒-->
        <property name="minEvictableIdleTimeMillis" value="300000" />

        <!--配置监控统计拦截的filters-->
        <property name="filters" value="stat" />
    </bean>

在AbstractRoutingDataSource实现抽象类的子类中添加两个数据源
在这里插入图片描述

<!--自定义存取数据源 《读写锋分离的第二种方式》-->
    <bean id="dataSource" class="com.bw.spring.datasource.CustomDataSource">
        <property name="targetDataSources">
            <map key-type="java.lang.String">
                <entry key="master" value-ref="dataSourceForRead" />
                <entry key="slave" value-ref="dataSourceForWrite" />
            </map>
        </property>
        <property name="defaultTargetDataSource" ref="dataSourceForWrite" />
    </bean>

其它配置均和spring配置相同即可。
启动spring完成后,spring会根据配置文件自动在CustomDataSource配置两个数据源。
在这里插入图片描述

三、如何选择数据源

查看AbstractRoutingDataSource的getConnection方法
在这里插入图片描述
我们在获取数据库链接前都会先执行determineTargetDataSource()方法

在这里插入图片描述
determineTargetDataSource又会通过determineCurrentLookupKey方法根据key获取不同的数据源,那么我们的AbstractRoutingDataSource子类就必须实现determineCurrentLookupKey方法,通过此方法帮助我们选择不同的数据源。

设置一个CustomDataSourceHolder设置获取key,需要保证线程安全。
在这里插入图片描述
在这里插入图片描述
我们自定义一个注解帮助我们在service层切换选择数据源
在这里插入图片描述
在定义一个aop类,在方法执行前判断设置哪一种数据源
在这里插入图片描述
我们只需要在方法上添加注解即可动态的切换数据源
在这里插入图片描述

四、多数据源切换

实际情况下,我们不会是单一的读写数据源,往往是多个读数据源。
在这里插入图片描述
直接上代码,我们可以通过设置从库名称为slave1、slave2.。。。。。。.,通过轮询的方式获取从库。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

第二种方案

在mapper的dao层加入自定义注解使用不同的数据源。

<bean id="sqlSessionFactoryForRead" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--配置数据库连接池-->
        <property name="dataSource" ref="dataSourceForRead" />
        <!--配置mybatis全局配置文件mybatis-config.xml-->
        <property name="configLocation" value="classpath:mybatis-config.xml" />
        <!--扫描model包-->
        <property name="typeAliasesPackage" value="com.bw.model" />
        <!--扫描sql xml配置文件-->
        <property name="mapperLocations" value="classpath:mapper/*.xml" />
    </bean>
    <!--配置sql sessionFactoryForWrite  《读写分离的第一种方式》-->
    <bean id="sqlSessionFactoryForWrite" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--配置数据库连接池-->
        <property name="dataSource" ref="dataSourceForWrite" />
        <!--配置mybatis全局配置文件mybatis-config.xml-->
        <property name="configLocation" value="classpath:mybatis-config.xml" />
        <!--扫描model包-->
        <property name="typeAliasesPackage" value="com.bw.model" />
        <!--扫描sql xml配置文件-->
        <property name="mapperLocations" value="classpath:mapper/*.xml" />
    </bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--注入sql sessionFactory-->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryForRead" />
        <!--扫描的dao接口包位置-->
        <property name="basePackage" value="com.bw.dao" />
        <!--读数据源注解类-->
        <property name="annotationClass" value="com.bw.customannotations.DatasourceRead" />
    </bean>
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--注入sql sessionFactory-->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryForWrite" />
        <!--扫描的dao接口包位置-->
        <property name="basePackage" value="com.bw.dao" />
        <!--写数据源注解类-->
        <property name="annotationClass" value="com.bw.customannotations.DatasourceWrite" />
    </bean>
<bean id="transactionManagerForRead" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSourceForRead" />
    </bean>
    <bean id="transactionManagerForWrite" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSourceForWrite" />
    </bean>

在这里插入图片描述

参考

添加链接描述

代码配置文件

添加链接描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值