Java中使用Shardingsphere-JDBC进行分库分表的使用方法(精简)

1.pom.xml中添加依赖

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

<!--相关基础依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>


2. application.yml中添加相关配

2.1 不分库分表的基础连接配置

 spring:
  shardingsphere:
   datasource:
    names: s1
    s1:
     type: com.alibaba.druid.pool.DruidDataSource
     driver-class-name: com.mysql.cj.jdbc.Driver
     url: jdbc:mysql://localhost:3306/mydb?serverTimezone=GMT%2B8
     username: root
     password: root
   props:
    sql:

     #是否打印sql
     show: true

*注意:这样配的话,跟操作单库单表的数据源配置效果一样


2.2 不分库但分表的连接配置

 spring:

  shardingsphere:
   datasource:
    names: s1
    s1:
     type: com.alibaba.druid.pool.DruidDataSource
     driver-class-name: com.mysql.cj.jdbc.Driver
     url: jdbc:mysql://localhost:3306/mydb?serverTimezone=GMT%2B8
     username: root
     password: root
   props:
    sql:
     show: true
   sharding:
    #分表
    tables:
     #参与分表的表名(虚拟表名)
     test:
      #分几个表,这里是两个,test_1和test_2
      actual-data-nodes: s1.test_$->{1..2}
      key-generator:
       #主键
       column: tid
       #主键填值,雪花
       type: SNOWFLAKE
      table-strategy:
       #主键分表路由策略
       inline:
        sharding-column: tid
        #这里采用偶数键值去test_1表,奇数键值去test_2表
        algorithm-expression: test_$->{tid%2+1}

2.3 分库分表的连接配置

 spring:

  shardingsphere:
   datasource:
    names: s1,s2
    s1:
     type: com.alibaba.druid.pool.DruidDataSource
     driver-class-name: com.mysql.cj.jdbc.Driver
     url: jdbc:mysql://localhost:3306/mydb1?serverTimezone=GMT%2B8
     username: root
     password: root

    s2:
     type: com.alibaba.druid.pool.DruidDataSource
     driver-class-name: com.mysql.cj.jdbc.Driver
     url: jdbc:mysql://localhost:3307/mydb2?serverTimezone=GMT%2B8
     username: root
     password: root
   props:
    sql:
     show: true
   sharding:
    #分表
    tables:
     #参与分表的表名(虚拟表名)
     test:
      #分库分表关键
      actual-data-nodes: s$->{1..2}.test_$->{1..2}
      key-generator:
       #主键
       column: tid
       #主键填值,雪花
       type: SNOWFLAKE
      table-strategy:
       #主键分表路由策略
       inline:
        sharding-column: tid
        #这里采用偶数键值去test_1表,奇数键值去test_2表
        algorithm-expression: test_$->{tid%2+1}

      data-strategy:
       #主键分库路由策略
       inline:
        sharding-column: tid
        #这里采用偶数键值去s1库,奇数键值去s2库
        algorithm-expression: s_$->{tid%2+1}

 

2.3 读写分离(mysql实现配置了主从架构)分库分表的连接配置

 spring:

  shardingsphere:
   datasource:
    names: m1,s1
    m1:
     type: com.alibaba.druid.pool.DruidDataSource
     driver-class-name: com.mysql.cj.jdbc.Driver
     url: jdbc:mysql://localhost:3306/mydb?serverTimezone=GMT%2B8
     username: root
     password: root

    s1:
     type: com.alibaba.druid.pool.DruidDataSource
     driver-class-name: com.mysql.cj.jdbc.Driver
     url: jdbc:mysql://localhost:3307/mydb?serverTimezone=GMT%2B8
     username: root
     password: root
   props:
    sql:
     show: true
   sharding:
    #分表
    tables:
     #参与分表的表名(虚拟表名)
     test:
      #分库分表关键
      actual-data-nodes: ms0.test_$->{1..2}
      key-generator:
       #主键
       column: tid
       #主键填值,雪花
       type: SNOWFLAKE
      table-strategy:
       #主键分表路由策略
       inline:
        sharding-column: tid
        #这里采用偶数键值去test_1表,奇数键值去test_2表
        algorithm-expression: test_$->{tid%2+1}

    #主从规则

    master-slave-rules:

     #规则一,名字随意,我这里用ms0表示

     ms0:

      master-data-source-name: m0

      #这里可以看出从库可以配多个

      slave-data-source-names[0]: s0

      

 3.分库分表路由策略

 shardingsphere为我们提供了以下几种策略类型:

  inline(内联),standard(标准),complex(复杂),hint(强制)

 

3.1 inline

#分片策略(test是我们的逻辑表,这里对应实际表test_1和test_2)

spring.shardingsphere.sharding.tables.test.table-strategy.inline.sharding-column=tid
spring.shardingsphere.sharding.tables.test.table-strategy.inline.algorithm-expression=test_$->{tid%2+1}
#分库策略
spring.shardingsphere.sharding.tables.test.database-strategy.inline.sharding-column=tid
spring.shardingsphere.sharding.tables.test.database-strategy.inline.algorithm-expression=s$->{tid%2+1}

*注:只支持分片主键的精确路由,不支持范围查询、模糊查询、联表查询。

 

3.2 standard(需要实现PreciseShardingAlgorithm和RangeShardingAlgorithm接口)

#分片策略

spring.shardingsphere.sharding.tables.test.table-strategy.standard.sharding-column=tid
spring.shardingsphere.sharding.tables.test.table-strategy.standard.precise-algorithm-class-name=com.shardingDemo.algorithem.MyPreciseTableShardingAlgorithm
spring.shardingsphere.sharding.tables.test.table-strategy.standard.range-algorithm-class-name=com.shardingDemo.algorithem.MyRangeTableShardingAlgorithm
#分库策略

spring.shardingsphere.sharding.tables.test.database-strategy.standard.sharding-column=tid
spring.shardingsphere.sharding.tables.test.database-strategy.standard.precise-algorithm-class-name=com.shardingDemo.algorithem.MyPreciseDSShardingAlgorithm
spring.shardingsphere.sharding.tables.test.database-strategy.standard.range-algorithm-class-name=com.shardingDemo.algorithem.MyRangeDSShardingAlgorithm

*注:需要定制实现精确路由和范围路由的逻辑类,也就是自己编码路由逻辑。

 

3.3 complex(需要实现ComplexKeysShardingAlgorithm接口)

#分片策略(这里用了两个表的主键tid和uid)

spring.shardingsphere.sharding.tables.test.table-strategy.complex.sharding-columns= tid, uid
spring.shardingsphere.sharding.tables.test.table-strategy.complex.algorithm-class-name=com.shardingDemo.algorithem.MyComplexTableShardingAlgorithm

#分库策略(这里用了两个表的主键tid和uid)
spring.shardingsphere.sharding.tables.test.database-strategy.complex.sharding-columns=tid, uid
spring.shardingsphere.sharding.tables.test.database-strategy.complex.algorithm-class-name=com.shardingDemo.algorithem.MyComplexDSShardingAlgorithm

*注:需要定制实现多表关联路由逻辑类。

 

3.4 hint(需要实现HintShardingAlgorithm接口)

 spring.shardingsphere.sharding.tables.course.table-strategy.hint.algorithm-class-name=com.shardingDemo.algorithem.MyHintTableShardingAlgorithm

*注:需要定制实现指定路由逻辑类,在使用查询语句时加上此规则后,可以去指定库表查询数据。

用法举例:  

  HintManager hintManager = HintManager.getInstance();
  hintManager.addTableShardingValue("test", 2);  //去test_2表查数据
  List<Test> tests= testMapper.selectList(null);
  tests.forEach(test-> System.out.println(test));
  hintManager.close();

 

4. 关于广播表和绑定表

 

4.1 广播表

分库以后每个库都有的全数据表这种表的数据一般变动很小,例如:字典表和状态表,这些表的数据在每一个库里都应该是一致的。

spring.shardingsphere.sharding.broadcast-tables=t_dict
spring.shardingsphere.sharding.tables.t_dict.key-generator.column=dict_id
spring.shardingsphere.sharding.tables.t_dict.key-generator.type=SNOWFLAKE

 

4.2 绑定表

当我们的查询条件依赖广播表时,也就是某逻辑表的字段的值依赖于一张广播表时,为避免联表查询产生笛卡尔积,则需要使用绑定规则。

spring.shardingsphere.sharding.binding-tables[0]=test,t_dict

 

5. 总结

使用分库分表的初衷是为了解决海量数据查询较慢的问题,列入当一张表的数据记录超过500万条或者单表容量大于2GB是则需要考虑分库分表,

但是分库分表会带来许多设计上和生产上的麻烦,增加逻辑复杂度和查询语句的使用限制,所以不要滥用分库分表,能不分就不分。另外分库分

表最好是在程序设计之初提前预估当前业务的数据增长量是否需要设计成分库分表架构,如果某个业务表比如订单表,他的增常量肯定每年都很

大,这个时候这张业务表就需要设计成分表,而用户表这种业务表起初可能增长势头很猛,但是经过两三年,数据基本上就稳定了,不会有较大

变动,那么,可以考虑设计此表时将表字段进行垂直切割,将常用字段放进用户表,而不常用字段放进用户关联表,但不做分表或分库。总之,

这是一个考验你业务和程序架构双项经验的事情。

 

posted @ 2021-11-04 16:39  秋末午后的阳光  阅读(1418)  评论(0编辑  收藏  举报