基于alibaba的druid实现多数据源读写分离

总体步骤:

1.配置多个数据源:分别为主数据源(用于写操作)和从数据源(用于读操作)。
2.实现动态数据源切换:通过 AbstractRoutingDataSource 或者自定义的 RoutingDataSource 类来决定每个请求使用哪个数据源。
3.配置事务管理器:确保事务正确处理。
4.整合 MyBatis:需要配置 SqlSessionFactory 并集成到 Spring 中

下面做个简单示例:

1.配置文件application.yaml新增多数据源配置项

spring:
  datasource:
    multi-datasource: true
    druid:
      master:
        url: jdbc:mysql://localhost:3306/master_db
        username: user
        password: pass
        driver-class-name: com.mysql.cj.jdbc.Driver
      slave:
        url: jdbc:mysql://localhost:3306/slave_db
        username: user
        password: pass
        driver-class-name: com.mysql.cj.jdbc.Driver

2.新建config类,配置多数据源


@Configuration
public class DruidDataSourceConfig {

    @Autowired
    private Environment env;

    @Bean(name = "masterDataSource")
    public DataSource master() {
        return DruidDataSourceBuilder.create()
                .configurationProperties(env.getProperty("spring.datasource.druid.master"))
                .build();
    }

    @Bean(name = "slaveDataSource")
    public DataSource slave() {
        return DruidDataSourceBuilder.create()
                .configurationProperties(env.getProperty("spring.datasource.druid.slave"))
                .build();
    }

    @Bean
    public DynamicDataSource dataSource(@Qualifier("masterDataSource") DataSource master,
                                        @Qualifier("slaveDataSource") DataSource slave) {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DatabaseType.MASTER, master);
        targetDataSources.put(DatabaseType.SLAVE, slave);

        DynamicDataSource dataSource = new DynamicDataSource();
        dataSource.setTargetDataSources(targetDataSources);
        dataSource.setDefaultTargetDataSource(master);
        return dataSource;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        return factoryBean.getObject();
    }

    @Bean
    public DataSourceTransactionManager transactionManager(@Qualifier("masterDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}

3.新建多数据源选择策略

public class DataSourceContextHolder {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    public static void setDataSourceType(String dataSourceType) {
        contextHolder.set(dataSourceType);
    }

    public static String getDataSourceType() {
        return contextHolder.get();
    }
}

4.关键点:通过org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource.

determineCurrentLookupKey实现动态数据源切换
public class DynamicDataSource extends AbstractRoutingDataSource {

    private static final Logger logger = LoggerFactory.getLogger(DynamicDataSource.class);
    public static final Map<DatabaseType, List<String>> METHOD_TYPE_MAP = new HashMap<>();

    @Nullable
    @Override
    protected Object determineCurrentLookupKey() {
        DatabaseType type = DatabaseContextHolder.getDatabaseType();
        return type;
    }

    public void setMethodType(DatabaseType type, String content) {
        List<String> list = Arrays.asList(content.split(","));
        METHOD_TYPE_MAP.put(type, list);
    }

}

5.在mybatis服务层调用(一般这里可通过切面aspect进行动态切换,根据你的数据源配置的规则, 通过DataSourceContextHolder.setDataSourceType实现动态切换,记得在切面完成后,清除掉数据源)

@Service
public class MyService {

    @Autowired
    private MyDao myDao;

    @Transactional
    public void updateSomething() {
        DataSourceContextHolder.setDataSourceType(DatabaseType.MASTER.name());
        myDao.updateSomething();
    }

    public List<Something> getSomething() {
        DataSourceContextHolder.setDataSourceType(DatabaseType.SLAVE.name());
        return myDao.getSomething();
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值