Shardingsphere 5与Dynamic Datasource配合实现多数据源读写分离

引言

在现代的应用程序中,使用多个数据源对数据库进行读写操作是一种常见的需求。读写分离是一种常见的数据库优化技术,可以将读操作分配给多个从数据库,从而提高系统的并发处理能力和读写性能。在本文中,我们将介绍如何使用Shardingsphere 5与Dynamic Datasource配合实现多数据源读写分离。

Shardingsphere简介

Shardingsphere是一个开源的分布式数据库中间件,支持多种关系型和非关系型数据库。它提供了一整套数据库分片、读写分离、分布式事务等功能,可以帮助开发者更方便地进行数据库的水平拆分和扩容。

Dynamic Datasource简介

Dynamic Datasource是一个简化多数据源配置的工具库,它可以动态地在运行时切换数据源,避免了配置文件的重启和应用程序的重启。

需求分析

假设我们有一个电商系统,系统中有两个数据库,一个用于读操作,一个用于写操作。我们希望能够将读操作分发给读库,写操作分发给写库,以提高系统的性能和可伸缩性。

实现步骤

第一步:添加依赖

首先,我们需要在项目的pom.xml文件中添加Shardingsphere和Dynamic Datasource的依赖。

<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>shardingsphere-jdbc-core</artifactId>
    <version>5.0.0</version>
</dependency>

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.4.3</version>
</dependency>

第二步:配置数据源

在Spring Boot的配置文件中,我们可以配置Shardingsphere和Dynamic Datasource的数据源。

spring:
  shardingsphere:
    datasource:
      names: ds0, ds1
      ds0:
        url: jdbc:mysql://localhost:3306/db_read?useSSL=false&characterEncoding=utf8
        username: root
        password: 123456
        driver-class-name: com.mysql.jdbc.Driver
      ds1:
        url: jdbc:mysql://localhost:3306/db_write?useSSL=false&characterEncoding=utf8
        username: root
        password: 123456
        driver-class-name: com.mysql.jdbc.Driver

dynamic:
  datasource:
    names: ds0, ds1
    ds0:
      url: jdbc:mysql://localhost:3306/db_read?useSSL=false&characterEncoding=utf8
      username: root
      password: 123456
      driver-class-name: com.mysql.jdbc.Driver
    ds1:
      url: jdbc:mysql://localhost:3306/db_write?useSSL=false&characterEncoding=utf8
      username: root
      password: 123456
      driver-class-name: com.mysql.jdbc.Driver

第三步:配置Shardingsphere

接下来,我们需要配置Shardingsphere的读写分离规则。

@Configuration
public class ShardingConfig {

    @Autowired
    private DataSource dataSource;

    @Bean
    public DataSource dataSource() {
        return new DynamicDataSource();
    }

    @Primary
    @Bean("dynamicDataSource")
    public DataSource dynamicDataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("ds0", dataSource);
        targetDataSources.put("ds1", dataSource);
        dynamicDataSource.setTargetDataSources(targetDataSources);
        dynamicDataSource.setDefaultTargetDataSource(dataSource);
        return dynamicDataSource;
    }

    @Bean
    public DataSourceTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dynamicDataSource());
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dynamicDataSource());
        return sessionFactory.getObject();
    }
}

第四步:编写业务代码

现在,我们可以编写业务代码来测试读写分离是否生效了。

@Mapper
public interface UserMapper {

    @Select("SELECT * FROM user")
    @DataSource("ds0")
    List<User> findAll();

    @Insert("INSERT INTO user (name, age) VALUES (#{name}, #{age})")
    @DataSource("ds1")
    void save(User user