使用MyCat做读写分离
前面一文配置了mysql的主从复制,我们可以使用mycat配置读写分离
读写分离,简单地说是把对数据库的读和写操作分开,以对应不同的数据库服务器。主数据库提供写操作,从数据库提供读操作,这样能有效地减轻单台数据库的压力。
MyCat主要配置文件
文件 |
说明 |
server.xml |
Mycat的配置文件,设置账号、参数等 |
schema.xml |
Mycat对应的物理数据库和数据库表的配置 |
rule.xml |
Mycat分片(分库分表)规则 |
server.xml配置
<!--设置两个数据库用户 -->
<user name="root" defaultAccount="true">
<property name="password">root</property>
<property name="schemas">TESTDB</property>
</user>
<user name="user">
<property name="password">user</property>
<property name="schemas">TESTDB</property>
<property name="readOnly">true</property>
</user>
schema.xml配置
<!-- TESTDB1 是mycat的逻辑库名称,链接需要用的 -->
<schema name="TESTDB1" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"></schema>
<!-- database 是MySQL数据库的库名 -->
<dataNode name="dn1" dataHost="localhost1" database="ms_test" />
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="3" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- 可以配置多个主从 -->
<writeHost host="host1" url="主库IP:3306" user="root" password="123456">
<!-- 可以配置多个从库 -->
<readHost host="host2" url="从库IP:3306" user="root" password="123456" />
</writeHost>
</dataHost>
SpringBoot项目整合动态数据源(读写分离)
application.yml
spring:
datasource:
###可读数据源
select:
jdbc-url: jdbc:mysql://127.0.0.1:8066/TESTDB1
driver-class-name: com.mysql.jdbc.Driver
username: user
password: user
####可写数据源
update:
jdbc-url: jdbc:mysql://127.0.0.1:8066/TESTDB1
driver-class-name: com.mysql.jdbc.Driver
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
DataSourceContextHolder
@Component
@Lazy(false)//禁止懒加载
public class DataSourceContextHolder {
// 采用ThreadLocal 保存本地多数据源
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
// 设置数据源类型
public static void setDbType(String dbType) {
contextHolder.set(dbType);
}
public static String getDbType() {
return contextHolder.get();
}
public static void clearDbType() {
contextHolder.remove();
}
}
DataSourceConfig
public class DataSourceConfig {
// 创建可读数据源
// application.properteis中对应属性的前缀
public DataSource dataSource1() {
return DataSourceBuilder.create().build();
}
// 创建可写数据源
// application.properteis中对应属性的前缀
public DataSource dataSource2() {
return DataSourceBuilder.create().build();
}
}
DynamicDataSource
//在Spring 2.0.1中引入了AbstractRoutingDataSource, 该类充当了DataSource的路由中介, 能有在运行时, 根据某种key值来动态切换到真正的DataSource上。
public class DynamicDataSource extends AbstractRoutingDataSource {
"selectDataSource") (
private DataSource selectDataSource;
"updateDataSource") (
private DataSource updateDataSource;
//这个是主要的方法,返回的是生效的数据源名称
protected Object determineCurrentLookupKey() {
System.out.println("DataSourceContextHolder:::" + DataSourceContextHolder.getDbType());
return DataSourceContextHolder.getDbType();
}
//配置数据源信息
public void afterPropertiesSet() {
Map<Object, Object> map = new HashMap<>();
map.put("selectDataSource", selectDataSource);
map.put("updateDataSource", updateDataSource);
setTargetDataSources(map);
setDefaultTargetDataSource(updateDataSource);
super.afterPropertiesSet();
}
}
DataSourceAOP
false) (
0) // Order设定AOP执行顺序 使之在数据库事务上先执行 (
public class SwitchDataSourceAOP {
// 这里切到你的方法目录
"execution(* com.dz.service.*.*(..))") (
public void process(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
if (methodName.startsWith("get")|| methodName.startsWith("find")
|| methodName.startsWith("list") || methodName.startsWith("select")) {
DataSourceContextHolder.setDbType("selectDataSource");
} else {
// 切换dataSource
DataSourceContextHolder.setDbType("updateDataSource");
}
}
}