美文网首页 技术博客Java
MYSQL读写分离核心方案代码

MYSQL读写分离核心方案代码

作者: 老生住长亭 | 来源:发表于2018-03-30 20:40 被阅读0次

此博客mysql的读写分离方案核心采用AOP,直接看核心代码。

1.AOP段的代码

@Component

@Aspect

public class DataSourceAspect {

    public static final ThreadLocal<String> handler = new ThreadLocal<>();

    public static String currentDataSource() {

        return handler.get();

    }

    @Before("execution(* com.example.model.mapper.*.*(..))")
    public void setDataSource(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("method name :" + methodName);

        String datasourceName = RoutingDataSource.MASTER;
        if (methodName.startsWith("select") || methodName.startsWith("count")) {
            datasourceName = RoutingDataSource.SLAVE;
        }

        System.out.println("[datasouceName] " + datasourceName);
        handler.set(datasourceName);
    }
}
2. 集成动态路由数据源:AbstractRoutingDataSource
public class RoutingDataSource extends AbstractRoutingDataSource {
    public static final String MASTER = "master";
    public static final String SLAVE = "slave";

    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceAspect.currentDataSource();
    }
}
  1. 数据源xml配置
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

      xsi:schemaLocation="http://www.springframework.org/schema/beans

       [http://www.springframework.org/schema/beans/spring-beans-3.0.xsd](http://www.springframework.org/schema/beans/spring-beans-3.0.xsd)">

    <bean id="masterDataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">

        <property name="driverClassName" value="${datasource.master.driver-class-name}"/>

        <property name="url" value="${datasource.master.url}"/>

        <property name="username" value="${datasource.master.username}"/>

        <property name="password" value="${datasource.master.password}"/>

        <!-- 配置初始化大小、最小、最大-->

        <property name="initialSize" value="5"/>

        <!-- 连接池中最少空闲maxIdle个连接-->

        <property name="minIdle" value="2"/>

        <!-- 连接池激活的最大数据库连接总数。设为0表示无限制-->

        <property name="maxActive" value="5"/>

        <!-- 最大建立连接等待时间,单位为ms,如果超过此时间将接到异常。设为-1表示无限制-->

        <property name="maxWait" value="60000"/>

        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒-->

        <property name="timeBetweenEvictionRunsMillis" value="60000"/>

        <!-- 配置连接池中连接可空闲的时间(针对连接池中的连接对象.空闲超过这个时间则断开,直到连接池中的连接数到minIdle为止),单位是毫秒-->

        <property name="minEvictableIdleTimeMillis" value="300000"/>

        <!-- 用来检测连接是否有效的sql,要求是一个查询语句-->

        <property name="validationQuery" value="SELECT 'x' FROM DUAL"/>

        <!-- 建议配置为true,不影响性能,并且保证安全性-->

        <property name="testWhileIdle" value="true"/>

        <!-- 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能-->

        <property name="testOnBorrow" value="false"/>

        <!-- 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能-->

        <property name="testOnReturn" value="false"/>

        <!-- 打开PSCache,并且指定每个连接上PSCache的大小(Oracle或mysql5.5及以上使用) -->

        <property name="poolPreparedStatements" value="true"/>

        <property name="maxPoolPreparedStatementPerConnectionSize" value="20"/>

        <!-- 配置监控统计拦截的filters -->

        <property name="filters" value="stat"/>

        <!-- 配置关闭长时间不使用的连接-->

        <!-- 是否清理removeAbandonedTimeout秒没有使用的活动连接,清理后并没有放回连接池(针对未被close的活动连接) -->

        <property name="removeAbandoned" value="true"/>

        <!-- 活动连接的最大空闲时间,1800秒,也就是30分钟-->

        <property name="removeAbandonedTimeout" value="1800"/>

        <!-- 连接池收回空闲的活动连接时是否打印消息-->

        <property name="logAbandoned" value="true"/>

    </bean>

    <bean id="slaveDataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">

        <property name="driverClassName" value="${datasource.slave.driver-class-name}"/>

        <property name="url" value="${datasource.slave.url}"/>

        <property name="username" value="${datasource.slave.username}"/>

        <property name="password" value="${datasource.slave.password}"/>

        <!-- 配置初始化大小、最小、最大-->

        <property name="initialSize" value="5"/>

        <!-- 连接池中最少空闲maxIdle个连接-->

        <property name="minIdle" value="5"/>

        <!-- 连接池激活的最大数据库连接总数。设为0表示无限制-->

        <property name="maxActive" value="5"/>

        <!-- 最大建立连接等待时间,单位为ms,如果超过此时间将接到异常。设为-1表示无限制-->

        <property name="maxWait" value="60000"/>

        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒-->

        <property name="timeBetweenEvictionRunsMillis" value="60000"/>

        <!-- 配置连接池中连接可空闲的时间(针对连接池中的连接对象.空闲超过这个时间则断开,直到连接池中的连接数到minIdle为止),单位是毫秒-->

        <property name="minEvictableIdleTimeMillis" value="300000"/>

        <!-- 用来检测连接是否有效的sql,要求是一个查询语句-->

        <property name="validationQuery" value="SELECT 'x' FROM DUAL"/>

        <!-- 建议配置为true,不影响性能,并且保证安全性-->

        <property name="testWhileIdle" value="true"/>

        <!-- 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能-->

        <property name="testOnBorrow" value="false"/>

        <!-- 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能-->

        <property name="testOnReturn" value="false"/>

        <!-- 打开PSCache,并且指定每个连接上PSCache的大小(Oracle或mysql5.5及以上使用) -->

        <property name="poolPreparedStatements" value="true"/>

        <property name="maxPoolPreparedStatementPerConnectionSize" value="20"/>

        <!-- 配置监控统计拦截的filters -->

        <property name="filters" value="stat"/>

        <!-- 配置关闭长时间不使用的连接-->

        <!-- 是否清理removeAbandonedTimeout秒没有使用的活动连接,清理后并没有放回连接池(针对未被close的活动连接) -->

        <property name="removeAbandoned" value="true"/>

        <!-- 活动连接的最大空闲时间,1800秒,也就是30分钟-->

        <property name="removeAbandonedTimeout" value="1800"/>

        <!-- 连接池收回空闲的活动连接时是否打印消息-->

        <property name="logAbandoned" value="true"/>

    </bean>

    <bean id="dataSource" class="com.example.rw.RoutingDataSource" primary="true">

        <property name="targetDataSources">

            <map key-type="java.lang.String">

                <!-- write -->

                <entry key="master" value-ref="masterDataSource"/>

                <!-- read -->

                <entry key="slave" value-ref="slaveDataSource"/>

            </map>

        </property>

        <property name="defaultTargetDataSource" ref="masterDataSource"/>

    </bean>

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

        <property name="dataSource" ref="masterDataSource"/>

    </bean>

</beans>

相关文章

网友评论

    本文标题:MYSQL读写分离核心方案代码

    本文链接:https://www.haomeiwen.com/subject/tjqwcftx.html