赞
踩
有道无术,术尚可求,有术无道,止于术。
本系列Spring Boot 版本 3.1.0
本系列ShardingSphere 版本 5.4.0
源码地址:https://gitee.com/pearl-organization/study-sharding-sphere-demo
水平分表是指通过某个字段(或某几个),根据某种规则将数据分散至多个表中,每个分片仅包含数据的一部分,和水平分库的思路相似,不过对象的重点转移到了表,用于解决了单一表数据量过大的问题,分表一般配合分库一起使用。
业务场景:某电商网站预计三年后,订单表数据量将达到2
亿,需要对订单表进行分库分表设计。
在只考虑2
亿数据量的情况下,将订单库拆分为两个库,订单表拆分为十张表。订单库根据订单ID
取模,偶数订单存入到偶数订单库,奇数订单存入到奇数订单库。针对订单数据,根据0 - 9
的尾数存入到对应的订单表中。
首先搭建两个数据库,并创建对应的数据表:
创建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>
使用代码生成器生成订单表相应的业务代码:
在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
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"
当前指数据表分布示意:
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
数据节点使用行表达式的配置如下:
# 规则配置
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]} # 实际数据节点,由数据源名 + 表名组成
订单库根据订单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 # 自定义的分片算法名称
订单表分表策略分片键使用订单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 # 自定义的分片算法名称
访问测试接口:
@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 "操作成功";
}
可以看到奇数的数据存入到了ds_order_1
库,偶数的数据存入到了ds_order_0
库,并且也按照ID
尾数存入到了对应的订单表:
访问测试接口:
@GetMapping("/list")
public List<OrderEntity> list() {
return orderService.list();
}
可以看到查询了两个节点,再聚合返回:
访问测试接口:
@GetMapping("/getById")
public Object getById(@RequestParam Long id) {
return orderService.getById(id);
}
会根据ID
计算出存储数据节点,再查询返回:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。