基于shardingsphere的读写分离方案

pom文件配置

xml 复制代码
<!-- Mybatis Plus的依赖,包括Mybatis和Mybatis Plus的核心库 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.3.2</version>
</dependency>

<!-- ShardingSphere的依赖 -->
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-core</artifactId>
    <version>5.0.0-alpha</version>
</dependency>

<!-- MySQL数据库驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.23</version>
</dependency>

接着,我们需要在application.yml中进行相关配置。

ShardingSphere配置

yaml 复制代码
spring:
  # 配置数据源
  shardingsphere:
    datasource:
      # 配置主库
      master:
        url: jdbc:mysql://127.0.0.1:3306/test?useSSL=false&serverTimezone=UTC
        username: root
        password: 123456
        driver-class-name: com.mysql.cj.jdbc.Driver
      # 配置从库1
      slave0:
        url: jdbc:mysql://127.0.0.1:3307/test?useSSL=false&serverTimezone=UTC
        username: root
        password: 123456
        driver-class-name: com.mysql.cj.jdbc.Driver
      # 配置从库2
      slave1:
        url: jdbc:mysql://127.0.0.1:3308/test?useSSL=false&serverTimezone=UTC
        username: root
        password: 123456
        driver-class-name: com.mysql.cj.jdbc.Driver
    # 配置读写分离规则
    sharding:
      default-data-source: master # 默认使用主库
      master-slave-rules:
        # 配置读写分离规则,每个库都是一主多从
        ms0:
          master-data-source-name: master
          slave-data-source-names:
            - slave0
            - slave1
          # 配置负载均衡算法,这里设置轮询策略
          load-balance-algorithm-type: round_robin

对应java代码

我们在MybatisPlusConfig中配置相关的Interceptor和DataSource。

java 复制代码
@Configuration
public class MybatisPlusConfig {

    @Autowired
    private DataSource dataSource;

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 配置分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }

    @Bean(name = "myRoutingDataSource")
    public DataSource myRoutingDataSource() throws SQLException {
        Map<String, DataSource> dataSourceMap = new HashMap<>(3);
        dataSourceMap.put("master", dataSource);
        dataSourceMap.put("slave0", createDataSource("jdbc:mysql://127.0.0.1:3307/test?useSSL=false&serverTimezone=UTC", "root", "123456"));
        dataSourceMap.put("slave1", createDataSource("jdbc:mysql://127.0.0.1:3308/test?useSSL=false&serverTimezone=UTC", "root", "123456"));

        ShardingRuleConfiguration shardingRuleConfiguration = new ShardingRuleConfiguration();
        shardingRuleConfiguration.setDefaultDataSourceName("master");

        // 配置分片规则
        shardingRuleConfiguration.setDefaultDatabaseShardingStrategyConfig(new StandardShardingStrategyConfiguration("user_id", new ModuloShardingTableAlgorithm()));
        shardingRuleConfiguration.setDefaultTableShardingStrategyConfig(new StandardShardingStrategyConfiguration("user_id", new ModuloShardingTableAlgorithm()));

        // 配置读写分离规则
        shardingRuleConfiguration.setMasterSlaveRuleConfigs(Collections.singletonList(new MasterSlaveRuleConfiguration("ms0", "master", Arrays.asList("slave0", "slave1"))));

        return ShardingSphereDataSourceFactory.createDataSource(dataSourceMap, Collections.singleton(shardingRuleConfiguration), new Properties());
    }

    private DataSource createDataSource(final String url, final String username, final String password) {
        HikariDataSource result = new HikariDataSource();
        result.setDriverClassName("com.mysql.cj.jdbc.Driver");
        result.setJdbcUrl(url);
        result.setUsername(username);
        result.setPassword(password);
        return result;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
        factoryBean.setDataSource(myRoutingDataSource());
        factoryBean.setPlugins(mybatisPlusInterceptor());
        return factoryBean.getObject();
    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplate() throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory());
    }

}

在这个配置中,我们创建了一个myRoutingDataSource,用于管理我们的多数据源。在这里,我们将master库作为默认数据源,然后配置了两个从库(slave0和slave1)。

接着,我们还需要配置分片规则和读写分离规则。这里,我们简单地配置了一下按照user_id字段进行分片,并按照轮询策略进行负载均衡的读写分离规则。

最后,在我们的Mapper接口中,我们可以使用@DS注解来指定数据源。

less 复制代码
public interface UserMapper extends BaseMapper<User> {
    @DS("master") // 指定数据源为主库
    @Override
    int insert(User entity);
    @DS("slave") // 指定数据源为从库
    @Override
    User selectById(Serializable id);
    @DS("slave")
    List<User> selectListByUserId(Integer userId);
}

这样,我们就完成了基于SpringBoot、Mybatis Plus、ShardingSphere实现读写分离的方案!

补充:

  1. 在数据库中建立表时,需要按照分片规则进行建表。例如,我们按照user_id进行分片,则需要对每个分片建立对应的表,例如user_0user_1等。在进行增删改查操作时,需要根据user_id进行路由。
  2. 在进行读写分离时,需要考虑到数据同步的问题。即,当主库增加或修改数据时,需要同步到从库中。在ShardingSphere中,可以设置同步方式,例如异步或同步等。
  3. 在ShardingSphere中,除了读写分离外,还有更多的分片策略可供选择。例如,按照哈希值进行分片、按照范围进行分片等等。根据实际场景选择合适的分片策略可以更好地提升性能。
  4. 在进行多数据源管理时,需要考虑到事务问题。例如,如果一个事务中需要涉及到多个数据源,就需要使用分布式事务来管理。ShardingSphere提供了XA、AT等分布式事务方案。
  5. 最好将ShardingSphere的配置分离出去,不要将其配置在application.yml中,这样更易于维护和管理。可以将配置写在单独的yaml文件中,并通过spring.config.import属性将其导入到SpringBoot中,例如:
yaml 复制代码
 # sharding-jdbc.yaml
spring:
  shardingsphere:
    # 配置数据源、分片规则和读写分离规则

然后,在application.yml中导入这个配置文件:

arduino 复制代码
# application.ymlspring:
  config:
    import: classpath:sharding-jdbc.yml
  1. 在ShardingSphere中,如果有多个表需要采用相同的分片策略,可以使用逻辑表来简化配置。例如,我们有两个表userorder,按照user_id进行分片,可以这样配置:
yaml 复制代码
 # 配置逻辑表user_order
tables:
  user_order:
    actualDataNodes: ds${0..1}.user_${0..3} # 分片规则# 其他配置
  1. 在进行数据分片时,需要考虑到数据分布的均衡问题。如果某个分片的数据量过大,会导致性能下降。可以考虑将分片键设计得更加合理,以实现数据分布的均衡。
  2. 在进行读写分离时,需要考虑到数据同步的问题。如果在从库上发生了读取操作,但是在主库中进行了写入操作,那么数据就会出现不一致的情况。可以考虑使用异步复制或半同步复制等机制来解决这个问题。
  3. 在ShardingSphere中,可以使用tracing-enabled属性来启用分片日志,以便于定位错误和问题。
  4. 最后,需要注意分片的成本和维护的难度。尽管分片可以提高系统性能,但是需要付出更多的成本和维护的难度。在进行分片之前,需要对系统架构进行全面的评估,并权衡利弊。
相关推荐
郑州吴彦祖7727 分钟前
【java】数据类型与变量以及操作符
java·intellij-idea
程序员大金8 分钟前
基于SpringBoot+Vue+MySQL的在线学习交流平台
java·vue.js·spring boot·后端·学习·mysql·intellij-idea
栀夏61312 分钟前
MongoDB 索引
数据库
吹老师个人app编程教学13 分钟前
阿里巴巴_java开发规范手册详解
java·开发语言
天上掉下来个程小白14 分钟前
Stream流的终结方法(一)
java·windows
qq_25183645716 分钟前
基于SpringBoot vue 医院病房信息管理系统设计与实现
vue.js·spring boot·后端
米饭是菜qy17 分钟前
MySql 事务
数据库·mysql
天上掉下来个程小白36 分钟前
请求响应-08.响应-案例
java·服务器·前端·springboot
大白_dev36 分钟前
数据校验的总结
java·开发语言