MYSQL读写分离核心方案代码
2018-03-30 本文已影响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();
}
}
- 数据源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>