ShardingSphere分库分表----取模和按日期分表

悠悠 2022-12-23 14:25 302阅读 0赞

shardingjdbc分库分表——取模和按时间分表

每天多学一点点~
话不多说,这就开始吧…

文章目录

  • shardingjdbc分库分表——取模和按时间分表
    • 1.前言
      1. 取模分库分表配置
      1. 分片策略简介
      1. 根据日期分库分表配置
    • 5.结语

1.前言

最近有个业务需要分库分表,遂研究了下sharing。网上列出了一些取模的分库分表实现,但是按照时间分库分表,或者二者结合的很少,遂在这里记录一下。
shrdingsphere官网 各位有兴趣的去官网看看,中文的。。。

  1. JDBC
    定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额外服务。 它使用客户端直连数据库,以 jar 包形式提供服务,无需额外部署和依赖,可理解为增强版的 JDBC 驱动,完全兼容 JDBC 和各种 ORM 框架。
  2. proxy
    类似于mycat。定位为透明化的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持。 目前提供 MySQL 和 PostgreSQL 版本,它可以使用任何兼容 MySQL/PostgreSQL 协议的访问客户端(如:MySQL Command Client, MySQL Workbench, Navicat 等)操作数据,对 DBA 更加友好。
  3. Sidecar
    定位为 Kubernetes 的云原生数据库代理,以 Sidecar 的形式代理所有对数据库的访问。 通过无中心、零侵入的方案提供与数据库交互的的啮合层,即 Database Mesh,又可称数据库网格。好像还在规划中

在这里插入图片描述

这里我选择了JDBC 方式。

2. 取模分库分表配置

  1. 引入依赖
    简单的springboot工程

    1. <dependency>
    2. <groupId>mysql</groupId>
    3. <artifactId>mysql-connector-java</artifactId>
    4. </dependency>
    5. <!--mybatis-->
    6. <dependency>
    7. <groupId>org.mybatis.spring.boot</groupId>
    8. <artifactId>mybatis-spring-boot-starter</artifactId>
    9. <version>2.0.0</version>
    10. </dependency>
    11. <!-- sharding apache最新孵化的版本 -->
    12. <dependency>
    13. <groupId>org.apache.shardingsphere</groupId>
    14. <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    15. <version>4.0.1</version>
    16. </dependency>
  2. 规则
    以订单为例,用 user_id 进行取模 分库 , order_id 进行取模分表
    boke_0 boke_1 两个库,每个库 t_order_0 t_order_1 两张表 ,共4张表

    CREATE TABLE t_order (
    order_id bigint(20) NOT NULL AUTO_INCREMENT COMMENT ‘订单id(雪花算法)’,
    user_id int(20) NOT NULL COMMENT ‘用户id’,
    address_id bigint(20) NOT NULL COMMENT ‘地址id’,
    status char(1) DEFAULT NULL COMMENT ‘订单状态’,
    create_time datetime DEFAULT NULL COMMENT ‘创建时间’,
    PRIMARY KEY (order_id) USING BTREE
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

  3. properties配置

    配置数据源 boke_1 boke_2

    spring.shardingsphere.datasource.names=b0,b1

    boke_0 数据源配置

    spring.shardingsphere.datasource.b0.type=com.zaxxer.hikari.HikariDataSource
    spring.shardingsphere.datasource.b0.driver-class-name=com.mysql.jdbc.Driver
    spring.shardingsphere.datasource.b0.jdbc-url=jdbc:mysql://localhost:3306/boke_0?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
    spring.shardingsphere.datasource.b0.username=root
    spring.shardingsphere.datasource.b0.password=root

    boke_1 数据源配置

    spring.shardingsphere.datasource.b1.type=com.zaxxer.hikari.HikariDataSource
    spring.shardingsphere.datasource.b1.driver-class-name=com.mysql.jdbc.Driver
    spring.shardingsphere.datasource.b1.jdbc-url=jdbc:mysql://localhost:3306/boke_1?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
    spring.shardingsphere.datasource.b1.username=root
    spring.shardingsphere.datasource.b1.password=root

  1. # 分库策略(水平) 以 user_id 取模 进行 分库
  2. spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=user_id
  3. spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=b$->{user_id % 2}
  4. # 绑定表 t_order 与 t_order_item
  5. spring.shardingsphere.sharding.binding-tables=t_order,t_order_item
  6. # t_order 分表策略
  7. # 节点 b0.t_order_0,b1.t_order_1,b0.t_order_0,b1.t_order_1
  8. spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=b$->{0..1}.t_order_$->{0..1}
  9. # 分表 id
  10. spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column=order_id
  11. # 分表策略 order_id 取模
  12. spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression=t_order_$->{order_id % 2}
  13. # 使用SNOWFLAKE算法生成主键
  14. spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
  15. spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE
  16. # 雪花算法的workId 机器为标识 0-1024
  17. spring.shardingsphere.sharding.tables.t_order.key-generator.props.worker.id=123
  18. # t_order_item 分表策略
  19. # 节点 b0.t_order_item_0,b0.t_order_item_1,b1.t_order_item_0,b1.t_order_item_1
  20. spring.shardingsphere.sharding.tables.t_order_item.actual-data-nodes=b$->{0..1}.t_order_item_$->{0..1}
  21. # 分表策略 order_id 取模
  22. spring.shardingsphere.sharding.tables.t_order_item.table-strategy.inline.sharding-column=order_id
  23. # 分表策略 根据id取模,确定数据最终落在那个表中
  24. spring.shardingsphere.sharding.tables.t_order_item.table-strategy.inline.algorithm-expression=t_order_item_$->{order_id % 2}
  25. # 使用SNOWFLAKE算法生成主键
  26. spring.shardingsphere.sharding.tables.t_order_item.key-generator.column=order_item_id
  27. spring.shardingsphere.sharding.tables.t_order_item.key-generator.type=SNOWFLAKE
  28. spring.shardingsphere.sharding.tables.t_order_item.key-generator.props.worker.id=123
  29. # 广播表 address
  30. spring.shardingsphere.sharding.broadcast-tables=t_address

这样配置好之后,其他就和springboot项目一样,直接用mybatis查询就可。

3. 分片策略简介

分片策略官网简介
包含分片键和分片算法,由于分片算法的独立性,将其独立抽离。真正可用于分片操作的是分片键 + 分片算法,也就是分片策略。目前提供 5 种分片策略。

  1. 标准分片策略
    对应 StandardShardingStrategy。提供对 SQ L语句中的 =, >, <, >=, <=, IN 和 BETWEEN AND 的分片操作支持。 StandardShardingStrategy 只支持单分片键,提供 PreciseShardingAlgorithm 和 RangeShardingAlgorithm 两个分片算法。 PreciseShardingAlgorithm 是必选的,用于处理 = 和 IN 的分片。 RangeShardingAlgorithm 是可选的,用于处理 BETWEEN AND, >, <, >=, <=分片,如果不配置 RangeShardingAlgorithm,SQL 中的 BETWEEN AND 将按照全库路由处理。
  2. 复合分片策略
    对应 ComplexShardingStrategy。复合分片策略。提供对 SQL 语句中的 =, >, <, >=, <=, IN 和 BETWEEN AND 的分片操作支持。 ComplexShardingStrategy 支持多分片键,由于多分片键之间的关系复杂,因此并未进行过多的封装,而是直接将分片键值组合以及分片操作符透传至分片算法,完全由应用开发者实现,提供最大的灵活度。
  3. Hint分片策略
    对应 HintShardingStrategy。通过 Hint 指定分片值而非从 SQL 中提取分片值的方式进行分片的策略。
  4. 不分片策略
    对应 NoneShardingStrategy。不分片的策略。

4. 根据日期分库分表配置

  1. 规则
    以订单为例,db 以 订单id 取模 分库, table 以 订单创建时间 分表
    即 boke_0 boke_1 两个库,每个库中 t_order_2020_1 —t_order_2021_12 共24张表。
  2. 写两个类,实现 PreciseShardingAlgorithm 精确分片算法,一个用于db取模,一个用于table按月份分片。
    DBShardingAlgorithm 用于 db 取模

    /*

    • @author :zjq
    • @date :2020/11/9 10:44
    • @description: TODO 数据表分表策略 TableShardingAlgorithm
    • @version: V1.0
    • @slogan: 天下风云出我辈,一入代码岁月催
      */
      @Slf4j
      public class DBShardingAlgorithm implements PreciseShardingAlgorithm {
      @Override
      public String doSharding(Collection availableTargetNames, PreciseShardingValue shardingValue) {

      1. System.out.println("DB PreciseShardingAlgorithm ");
      2. // 真实节点
      3. availableTargetNames.stream().forEach((item) -> {
      4. log.info("actual node db:{}", item);
      5. });
      6. log.info("logic table name:{},rout column:{}", shardingValue.getLogicTableName(), shardingValue.getColumnName());
      7. //精确分片
      8. log.info("column value:{}", shardingValue.getValue());
      9. long orderId = shardingValue.getValue();
      10. long db_index = orderId & (2 - 1);
      11. for (String each : availableTargetNames) {
      12. if (each.equals("b"+db_index)) {
      13. return each;
      14. }
      15. }
      16. throw new IllegalArgumentException();

      }
      }

TableShardingAlgorithm用于table按月份分片

  1. /*
  2. * @author :zjq
  3. * @date :2020/11/9 10:44
  4. * @description: TODO 数据表分表策略 TableShardingAlgorithm
  5. * @version: V1.0
  6. * @slogan: 天下风云出我辈,一入代码岁月催
  7. */
  8. @Slf4j
  9. public class TableShardingAlgorithm implements PreciseShardingAlgorithm<Date> {
  10. @Override
  11. public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Date> shardingValue) {
  12. System.out.println("table PreciseShardingAlgorithm ");
  13. // 真实节点
  14. availableTargetNames.stream().forEach((item) -> {
  15. log.info("actual node table:{}", item);
  16. });
  17. log.info("logic table name:{},rout column:{}", shardingValue.getLogicTableName(), shardingValue.getColumnName());
  18. //精确分片
  19. log.info("column value:{}", shardingValue.getValue());
  20. String tb_name = shardingValue.getLogicTableName() + "_";
  21. // 根据当前日期 来 分库分表
  22. Date date = shardingValue.getValue();
  23. String year = String.format("%tY", date);
  24. String mon =String.valueOf(Integer.parseInt(String.format("%tm", date))); // 去掉前缀0
  25. String dat = String.format("%td", date);
  26. // 选择表
  27. tb_name = tb_name + year + "_" + mon;
  28. System.out.println("tb_name:" + tb_name);
  29. for (String each : availableTargetNames) {
  30. System.out.println("t_order_:" + each);
  31. if (each.equals(tb_name)) {
  32. return each;
  33. }
  34. }
  35. throw new IllegalArgumentException();
  36. }
  37. }
  1. properties 配置
    db 以 订单id 取模 table 以 订单创建时间 分库

    配置数据源 boke_1 boke_2

    spring.shardingsphere.datasource.names=b0,b1
    spring.shardingsphere.sharding.default-data-source-name=b0

    boke_0 数据源配置

    spring.shardingsphere.datasource.b0.type=com.zaxxer.hikari.HikariDataSource
    spring.shardingsphere.datasource.b0.driver-class-name=com.mysql.jdbc.Driver
    spring.shardingsphere.datasource.b0.jdbc-url=jdbc:mysql://localhost:3306/boke_0?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai&relaxAutoCommit=true&zeroDateTimeBehavior=convertToNull
    spring.shardingsphere.datasource.b0.username=root
    spring.shardingsphere.datasource.b0.password=root

    boke_1 数据源配置

    spring.shardingsphere.datasource.b1.type=com.zaxxer.hikari.HikariDataSource
    spring.shardingsphere.datasource.b1.driver-class-name=com.mysql.jdbc.Driver
    spring.shardingsphere.datasource.b1.jdbc-url=jdbc:mysql://localhost:3306/boke_1?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai&relaxAutoCommit=true&zeroDateTimeBehavior=convertToNull
    spring.shardingsphere.datasource.b1.username=root
    spring.shardingsphere.datasource.b1.password=root

  1. spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=b$->{0..1}.t_order_$->{2020..2021}_$->{1..12}
  2. # 自定义 分片算法
  3. # 分库分片健 database-strategy 数据库策略
  4. spring.shardingsphere.sharding.tables.t_order.database-strategy.standard.sharding-column=order_id
  5. # 自定义 分片 策略
  6. spring.shardingsphere.sharding.tables.t_order.database-strategy.standard.precise-algorithm-class-name=com.boke.order.sharding.time.DBShardingAlgorithm
  7. # table-strategy 表 的 策略
  8. spring.shardingsphere.sharding.tables.t_order.table-strategy.standard.sharding-column=create_time
  9. spring.shardingsphere.sharding.tables.t_order.table-strategy.standard.precise-algorithm-class-name=com.boke.order.sharding.time.TableShardingAlgorithm
  10. # 使用SNOWFLAKE算法生成主键
  11. spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
  12. spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE
  13. # 雪花算法的workId 机器为标识 0-1024
  14. spring.shardingsphere.sharding.tables.t_order.key-generator.props.worker.id=123

这样就大功告成,经过测试,插入,分页查询,范围,精确查询,事务都是ok,但是因为选择了精确分片算法 ,分页和范围查询,会路由到2个db的24张表上,会有效率问题,所以要好好取舍,再研究研究~

5.结语

世上无难事,只怕有心人,每天积累一点点,fighting!!!

发表评论

表情:
评论列表 (有 0 条评论,302人围观)

还没有评论,来说两句吧...

相关阅读

    相关 分库ShardingSphere分片

    1. 背景    >        了解分片之前,我们需要知道为什么要分库分表,本质原因还是因为单表的数据库容量有限, > > 当数据量到达一定量级之后,数据库操作会变得很