vlambda博客
学习文章列表

使用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

@Configurationpublic class DataSourceConfig { // 创建可读数据源 @Bean(name = "selectDataSource") @ConfigurationProperties(prefix = "spring.datasource.select") // application.properteis中对应属性的前缀 public DataSource dataSource1() { return DataSourceBuilder.create().build();  } // 创建可写数据源 @Bean(name = "updateDataSource") @ConfigurationProperties(prefix = "spring.datasource.update") // application.properteis中对应属性的前缀 public DataSource dataSource2() { return DataSourceBuilder.create().build();  }}


DynamicDataSource

//在Spring 2.0.1中引入了AbstractRoutingDataSource, 该类充当了DataSource的路由中介, 能有在运行时, 根据某种key值来动态切换到真正的DataSource上。@Component@Primarypublic class DynamicDataSource extends AbstractRoutingDataSource { @Autowired @Qualifier("selectDataSource") private DataSource selectDataSource;
@Autowired @Qualifier("updateDataSource") private DataSource updateDataSource;//这个是主要的方法,返回的是生效的数据源名称 @Override protected Object determineCurrentLookupKey() { System.out.println("DataSourceContextHolder:::" + DataSourceContextHolder.getDbType()); return DataSourceContextHolder.getDbType(); }//配置数据源信息 @Override public void afterPropertiesSet() { Map<Object, Object> map = new HashMap<>(); map.put("selectDataSource", selectDataSource); map.put("updateDataSource", updateDataSource); setTargetDataSources(map); setDefaultTargetDataSource(updateDataSource); super.afterPropertiesSet(); }}

DataSourceAOP

@Aspect@Component@Lazy(false)@Order(0) // Order设定AOP执行顺序 使之在数据库事务上先执行public class SwitchDataSourceAOP { // 这里切到你的方法目录 @Before("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"); } }}