桃加橙 2022-05-15 04:16 采纳率: 100%
浏览 306
已结题

shardingjdbc default-database-strategy 配置问题

问题遇到的现象和发生背景

最近在使用 sharding-jdbc 做分库分表是遇到的问题,默认分库策略【default-database-strategy】要如何配置才能对所有表都生效
业务上是多租户的类型的项目,每个表都存在一个 租户id 【tenant_id】, 通过mybatis plus的sql拦截器自动拼接在sql语句最后。
默认的分库策略是对于 tenant_id 做取模运算,路由到不同的数据库中。
我预期的结果是 对于未单独配置策略的 表,可以走 默认的分库策略 【default-database-strategy】,而实际上并未生效

我关于 sharding-jdbc 的配置如下:

  shardingsphere:
    props:
      sql:
        show: true
    datasource:
      # 数据源
      names: master-0,slave-0,master-1,slave-1
      # 配置master 数据源
      master-0:
        # 配置druid数据源
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://mysql-server:3307/xxx-0?&serverTimezone=GMT%2b8&useSSL=false
        username: xxx
        password: xxx
        maxPoolSize: 100
        minPoolSize: 5
      slave-0:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://mysql-server:3307/xxx-0?&serverTimezone=GMT%2b8&useSSL=false
        username: jadows-0
        password: xxx
        maxPoolSize: xxx
        minPoolSize: 5
      master-1:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://mysql-server:3307/xxx-1?&serverTimezone=GMT%2b8&useSSL=false
        username: xxx
        password: xxx
        maxPoolSize: 100
        minPoolSize: 5
      slave-1:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://mysql-server:3307/xxx-1?&serverTimezone=GMT%2b8&useSSL=false
        username: xxx
        password: xxx
        maxPoolSize: 100
        minPoolSize: 5
    sharding:
      default-database-strategy:
        inline:
          sharding-column: tenant_id
          algorithm-expression: master-$->{tenant_id % 2}
      default-table-strategy:
        none:
      tables:
        # login_record 逻辑表
        login_record:
          # 数据节点:数据源$->{0..N}.逻辑表名$->{0..N}
          actual-data-nodes: master-$->{0..1}.login_record_$->{0..2}
          # 拆分库策略
          database-strategy:
            inline:
              # 分片字段
              sharding-column: tenant_id
              algorithm-expression: master-$->{tenant_id % 2}
          # 拆分表策略
          table-strategy:
            inline:
              # 分片字段(分片键)
              sharding-column: id
              # 分片算法表达式
              algorithm-expression: login_record_$->{ id % 3 }
      broadcast-tables:
        - tenant
      # 读写分离配置
      master-slave-rules:
        master-0:
          master-data-source-name: master-0
          slave-data-source-names: slave-0
        master-1:
          master-data-source-name: master-1
          slave-data-source-names: slave-1

情况1) 未配置 user 表的 分表策略,查询 user 表

 @Test
    public void test() {
        List<User> list = userService.list();
        System.out.println(list);

        List<User> l2 = userService.list();
        System.out.println(l2);
    }

执行上述两个查询,执行结果:

Actual SQL: slave-0 ::: SELECT id,..., created, tenant_id FROM `user` WHERE `user`.tenant_id = 0

Actual SQL: slave-1 ::: SELECT id,..., created, tenant_id FROM `user` WHERE `user`.tenant_id = 0

可以看到 ,master-slave 的策略生效,两次查询分别命中 slave-0 库 和 slave-1 库,而 default-database-stragegy 策略没有生效 【 预期:默认分库策略根据 tenant_id 取模,tenant_id 为 0 时 路由至 master-0 库,再根据 master-0 配置的的读写分离策略,两次查询都应该命中 slave-0 库】

情况2) 配置了 login_record 表的分表策略,查询 login_record 表
login_record 不按照 tenant_id 做分库【 记录用户的登录信息,未登录下不知道 tenant_id,所以取id 做分库字段 】,login_record 分为三张表,分别是

login_record_0
login_record_1
login_record_2
@Test
    public void loginRecordTest() {
        List<LoginRecord> list = loginRecordService.list();
        System.out.println(list);

  // 配置了 tables 策略 ,正确执行
        List<LoginRecord> list = loginRecordService.list();
        System.out.println(list);

        List<LoginRecord> list2 = loginRecordService.list();
        System.out.println(list2);

        List<LoginRecord> list3 = loginRecordService.list();
        System.out.println(list3);

        List<LoginRecord> list4 = loginRecordService.list();
        System.out.println(list4);
    }

执行结果:

Actual SQL: slave-0 ::: SELECT id, user_name, ... FROM login_record_0 WHERE login_record_0.tenant_id = 0

Actual SQL: slave-0 ::: SELECT id, user_name, ... FROM login_record_1 WHERE login_record_1.tenant_id = 0

Actual SQL: slave-0 ::: SELECT id, user_name,... FROM login_record_2 WHERE login_record_2.tenant_id = 0

单独配置 table-statagy 时,符合预期。所有查询只命中 slave-0 库。

sharding-jdbc 及 springboot 版本:

            <dependency>
                <groupId>org.apache.shardingsphere</groupId>
                <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
                <version>4.1.1</version>
            </dependency>

          <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.3.12.RELEASE</version>
          </dependency>

问题

需要如何配置,才能使得 数据库中所有的表 都支持默认的分库策略?

  • 写回答

1条回答 默认 最新

  • a1767028198 2022-05-15 13:01
    关注

    你怕是理解错了默认分库策略的作用范围:

    img


    他是在你的表已经确定分片的基础上,才会起作用,而不是你想的,是张表就分库
    如果你想要一堆表都要加上分库逻辑,要么自己一个个的配置,要么就自己手动在SpringBootShardingRuleConfigurationProperties初始化完成后,手动添加到SpringBootShardingRuleConfigurationProperties中(源码中我暂时没看到扩展点,允许你搞事情)

    img


    手动加入(可以将这部分的表名,全部配置到yml或者数据库,然后一次性加入到tables中)

    img


    img

    测试结果:

    img


    img

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 5月23日
  • 已采纳回答 5月15日
  • 修改了问题 5月15日
  • 修改了问题 5月15日
  • 展开全部

悬赏问题

  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料
  • ¥15 使用R语言marginaleffects包进行边际效应图绘制