当前位置:   article > 正文

ShardingSphere 5.x 系列【11】水平分表_shardingsphere5.4水平分表

shardingsphere5.4水平分表

有道无术,术尚可求,有术无道,止于术。

本系列Spring Boot 版本 3.1.0

本系列ShardingSphere 版本 5.4.0

源码地址:https://gitee.com/pearl-organization/study-sharding-sphere-demo

1. 概述

水平分表是指通过某个字段(或某几个),根据某种规则将数据分散至多个表中,每个分片仅包含数据的一部分,和水平分库的思路相似,不过对象的重点转移到了表,用于解决了单一表数据量过大的问题,分表一般配合分库一起使用。

2. 案例演示

业务场景:某电商网站预计三年后,订单表数据量将达到2亿,需要对订单表进行分库分表设计。

2.1 方案设计

在只考虑2亿数据量的情况下,将订单库拆分为两个库,订单表拆分为十张表。订单库根据订单ID取模,偶数订单存入到偶数订单库,奇数订单存入到奇数订单库。针对订单数据,根据0 - 9的尾数存入到对应的订单表中。
在这里插入图片描述

2.2 环境搭建

首先搭建两个数据库,并创建对应的数据表:
在这里插入图片描述
在这里插入图片描述

创建Spring Boot 3.1基础工程,并引入相关依赖:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
            <version>3.5.5</version>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.21</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-jdbc-core</artifactId>
            <version>5.4.0</version>
        </dependency>
        <!--java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory-->
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>2.3.8</version>
        </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

使用代码生成器生成订单表相应的业务代码:
在这里插入图片描述

2.3 数据源配置

resources目录下新建level-table-sharding-config.yml配置文件,存放ShardingSphere数据源、分片规则等配置信息。

application.yml文件中指定YAML配置文件:

server:
  port: 8086
spring:
  datasource:
    # 配置 DataSource Driver
    driver-class-name: org.apache.shardingsphere.driver.ShardingSphereDriver
    # 指定 YAML 配置文件
    url: jdbc:shardingsphere:classpath:level-table-sharding-config.yml

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

level-table-sharding-config.yml配置文件中添加订单库数据源:

# 数据源配置
dataSources:
  # 订单库_偶数
  ds_order_0: # 逻辑名称
    dataSourceClassName: com.zaxxer.hikari.HikariDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.56.101:3308/order
    username: root
    password: "root"
  # 订单库_奇数
  ds_order_1:
    dataSourceClassName: com.zaxxer.hikari.HikariDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.56.101:3306/order
    username: root
    password: "root"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

2.4 数据节点

当前指数据表分布示意:

ds_order_0
  ├── t_order_0
  ├── t_order_2
  ├── t_order_4
  ├── t_order_6
  ├── t_order_8
ds_order_1
  ├── t_order_1
  ├── t_order_3
  ├── t_order_5
  ├── t_order_7
  ├── t_order_9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

数据节点使用行表达式的配置如下:

# 规则配置
rules:
  # 分片规则
  - !SHARDING
    # 分片表
    tables:
      t_order: # 逻辑表名称
        actualDataNodes: ds_order_0.t_order_${[0,2,4,6,8]},ds_order_1.t_order_${[1,3,5,7,9]} # 实际数据节点,由数据源名 + 表名组成
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2.5 分库策略

订单库根据订单ID取模,偶数订单存入到偶数订单库,奇数订单存入到奇数订单库。分片键使用订单ID,分片算法使用行表达式分片算法,算法表达式使用id % 2计算奇偶。

# 规则配置
rules:
  # 分片规则
  - !SHARDING
    # 分片算法名称和配置
    shardingAlgorithms:
      # 分库
      database_inline: # 自定义的分片算法名称
        type: INLINE # 分片算法类型:INLINE(行表达式分片算法)
        props: # 分片算法属性配置
          algorithm-expression: ds_order_${id % 2} # 算法表达式
          allow-range-query-with-inline-sharding: true # 是否允许范围查询。注意:范围查询会无视分片策略,进行全路由,默认值false
    # 分片表
    tables:
      t_order: # 逻辑表名称
        actualDataNodes: ds_order_0.t_order_${[0,2,4,6,8]},ds_order_1.t_order_${[1,3,5,7,9]} # 实际数据节点,由数据源名 + 表名组成
        # 分库策略
        databaseStrategy:
          standard: # 分片策略类型 (standard:标准的,INLINE属于standard)
            shardingColumn: id # 分片列名称
            shardingAlgorithmName: database_inline # 自定义的分片算法名称
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

2.6 分表策略

订单表分表策略分片键使用订单ID,分片算法使用行表达式分片算法,算法表达式使用id % 10计算尾数,根据0 - 9的尾数存入到对应的订单表中。

完整的规则配置如下:

# 规则配置
rules:
  # 分片规则
  - !SHARDING
    # 分片算法名称和配置
    shardingAlgorithms:
      # 分库
      database_inline: # 自定义的分片算法名称
        type: INLINE # 分片算法类型:INLINE(行表达式分片算法)
        props: # 分片算法属性配置
          algorithm-expression: ds_order_${id % 2} # 算法表达式
          allow-range-query-with-inline-sharding: true # 是否允许范围查询。注意:范围查询会无视分片策略,进行全路由,默认值false
      # 分表
      table_inline:
        type: INLINE
        props:
          algorithm-expression: t_order_${id % 10}
          allow-range-query-with-inline-sharding: true
    # 分片表
    tables:
      t_order: # 逻辑表名称
        actualDataNodes: ds_order_0.t_order_${[0,2,4,6,8]},ds_order_1.t_order_${[1,3,5,7,9]} # 实际数据节点,由数据源名 + 表名组成
        # 分库策略
        databaseStrategy:
          standard: # 分片策略类型 (standard:标准的,INLINE属于standard)
            shardingColumn: id # 分片列名称
            shardingAlgorithmName: database_inline # 自定义的分片算法名称
        # 分表策略
        tableStrategy:
          standard: # 分片策略类型
            shardingColumn: id # 分片列名称
            shardingAlgorithmName: table_inline # 自定义的分片算法名称
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

3. 测试

3.1 插入数据

访问测试接口:

    @GetMapping("/save")
    public Object save() {
        OrderEntity orderEntity=new OrderEntity();
        orderEntity.setPhone(18888888888L);
        orderEntity.setAddress("湖南长沙");
        orderEntity.setOrderTime(LocalDateTime.now());
        orderEntity.setProductId(1L);
        orderEntity.setOrderTime(LocalDateTime.now());
        orderService.save(orderEntity);
        return "操作成功";
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

可以看到奇数的数据存入到了ds_order_1库,偶数的数据存入到了ds_order_0库,并且也按照ID尾数存入到了对应的订单表:
在这里插入图片描述

3.2 列表查询

访问测试接口:

    @GetMapping("/list")
    public List<OrderEntity> list() {
        return orderService.list();
    }
  • 1
  • 2
  • 3
  • 4

可以看到查询了两个节点,再聚合返回:
在这里插入图片描述

3.3 ID 查询

访问测试接口:

    @GetMapping("/getById")
    public Object getById(@RequestParam Long id) {
        return orderService.getById(id);
    }
  • 1
  • 2
  • 3
  • 4

会根据ID计算出存储数据节点,再查询返回:
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/756892
推荐阅读
相关标签
  

闽ICP备14008679号