1. マスターデータベースとスレーブデータベースの接続情報を設定する
# 主库配置
spring.datasource.master.jdbc-url=jdbc:mysql://ip:port/master?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
spring.datasource.master.username=master
spring.datasource.master.password=123456
spring.datasource.master.driver-class-name=com.mysql.jdbc.Driver
# 从库配置
spring.datasource.slave.jdbc-url=jdbc:mysql://ip:port/slave?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
spring.datasource.slave.username=slave
spring.datasource.slave.password=123456
spring.datasource.slave.driver-class-name=com.mysql.jdbc.Driver
2. マスター データベースとスレーブ データベースのデータ ソース構成クラスを作成します。
public class MasterDataSourceConfiguration {
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}
}
public class SlaveDataSourceConfiguration {
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build();
}
}
3. マスター/スレーブ データ ソース列挙の作成
public enum DataSourceTypeEnum {
/**
* 主库
*/
MASTER,
/**
* 从库
*/
SLAVE,
;
}
4. 動的ルーティング データ ソースを作成する
4j
public class DynamicRoutingDataSource extends AbstractRoutingDataSource {
"${DB_RW_SEPARATE_SWITCH:false}") (
private boolean dbRwSeparateSwitch;
protected Object determineCurrentLookupKey() {
if(dbRwSeparateSwitch && DataSourceTypeEnum.SLAVE.equals(DataSourceContextHolder.getDataSourceType())) {
log.info("DynamicRoutingDataSource 切换数据源到从库");
return DataSourceTypeEnum.SLAVE;
}
log.info("DynamicRoutingDataSource 切换数据源到主库");
// 根据需要指定当前使用的数据源,这里可以使用ThreadLocal或其他方式来决定使用主库还是从库
return DataSourceTypeEnum.MASTER;
}
}
5. 動的データソース構成クラスを作成する
"spring.datasource.master.jdbc-url") (
public class DynamicDataSourceConfiguration {
"dataSource") (
public DataSource dynamicDataSource(DataSource masterDataSource, DataSource slaveDataSource) {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DataSourceTypeEnum.MASTER, masterDataSource);
targetDataSources.put(DataSourceTypeEnum.SLAVE, slaveDataSource);
DynamicRoutingDataSource dynamicDataSource = new DynamicRoutingDataSource();
dynamicDataSource.setTargetDataSources(targetDataSources);
dynamicDataSource.setDefaultTargetDataSource(masterDataSource);
return dynamicDataSource;
}
}
6. DatasourceContextHolder クラスを作成し、ThreadLocal を使用して現在のスレッドのデータ ソース タイプを保存します。
public class DataSourceContextHolder {
private static final ThreadLocal<DataSourceTypeEnum> contextHolder = new ThreadLocal<>();
public static void setDataSourceType(DataSourceTypeEnum dataSourceType) {
contextHolder.set(dataSourceType);
}
public static DataSourceTypeEnum getDataSourceType() {
return contextHolder.get();
}
public static void clearDataSourceType() {
contextHolder.remove();
}
}
7. マスターおよびスレーブ データ ソースをマークするカスタム アノテーションを作成する
public MasterDataSource {
}
public SlaveDataSource {
}
8. アスペクトクラスを作成し、データベース操作をインターセプトし、アノテーション設定に従ってデータソースパラメータを切り替えます。
public class DataSourceAspect {
"@annotation(xxx.MasterDataSource)") (
public void setMasterDataSource(JoinPoint joinPoint) {
DataSourceContextHolder.setDataSourceType(DataSourceTypeEnum.MASTER);
}
"@annotation(xxx.SlaveDataSource)") (
public void setSlaveDataSource(JoinPoint joinPoint) {
DataSourceContextHolder.setDataSourceType(DataSourceTypeEnum.SLAVE);
}
"@annotation(xxx.MasterDataSource) || @annotation(xxx.SlaveDataSource)") (
public void clearDataSource(JoinPoint joinPoint) {
DataSourceContextHolder.clearDataSourceType();
}
}
9. サービス レイヤー メソッドでカスタム アノテーション タグを使用してデータ ソースをクエリします
public class TestService {
private TestDao testDao;
public Test test() {
return testDao.queryByPrimaryKey(11L);
}
}
10. データソース自動構成クラスを除外する
SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
1. 接続プールを使用する (例: ヒカリ)
# 主库配置
spring.datasource.master.jdbc-url=jdbc:mysql://ip:port/master?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
spring.datasource.master.username=master
spring.datasource.master.password=123456
spring.datasource.master.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.master.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.master.hikari.name=master
spring.datasource.master.hikari.minimum-idle=5
spring.datasource.master.hikari.idle-timeout=30
spring.datasource.master.hikari.maximum-pool-size=10
spring.datasource.master.hikari.auto-commit=true
spring.datasource.master.hikari.pool-name=DatebookHikariCP
spring.datasource.master.hikari.max-lifetime=1800000
spring.datasource.master.hikari.connection-timeout=30000
spring.datasource.master.hikari.connection-test-query=SELECT 1
# 从库配置
spring.datasource.slave.jdbc-url=jdbc:mysql://ip:port/slave?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
spring.datasource.slave.username=root
spring.datasource.slave.password=123456
spring.datasource.slave.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.slave.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.slave.hikari.name=master
spring.datasource.slave.hikari.minimum-idle=5
spring.datasource.slave.hikari.idle-timeout=30
spring.datasource.slave.hikari.maximum-pool-size=10
spring.datasource.slave.hikari.auto-commit=true
spring.datasource.slave.hikari.pool-name=DatebookHikariCP
spring.datasource.slave.hikari.max-lifetime=1800000
spring.datasource.slave.hikari.connection-timeout=30000
spring.datasource.slave.hikari.connection-test-query=SELECT 1
2. mybatis を統合し、書き込み時にメイン ライブラリに強制的に切り替える
({
"update", args = {MappedStatement.class, Object.class}), (type = Executor.class, method =
})
public class WriteInterceptor implements Interceptor {
public Object intercept(Invocation invocation) throws Throwable {
// 获取 SQL 类型
DataSourceTypeEnum dataSourceType = DataSourceContextHolder.getDataSourceType();
if(DataSourceTypeEnum.SLAVE.equals(dataSourceType)) {
DataSourceContextHolder.setDataSourceType(DataSourceTypeEnum.MASTER);
}
try {
// 执行 SQL
return invocation.proceed();
} finally {
// 恢复数据源 考虑到写入后可能会反查,后续都走主库
// DataSourceContextHolder.setDataSourceType(dataSourceType);
}
}
}
この記事は、WeChat パブリック アカウント - JD Cloud Developers (JDT_Developers) から共有されています。
侵害がある場合は、削除について [email protected] までご連絡ください。
この記事は「OSC ソース作成計画」に参加していますので、読んでいる方もぜひ参加し、共有してください。
{{名前}}
{{名前}}