本文是springboot2.x整合sharding-jdbc4.x完成指定字段进行分表的样例,全程干货无废话,值得一看呀~
先来讲下Sharding-Jdbc常见概念术语,站着统一水平线上,沟通无障碍,统一下专业术语
真实表
◦在分片的数据库中真实存在的物理表
◦比如订单表 product_order_0、product_order_1、product_order_2
逻辑表
◦水平拆分的数据库(表)的相同逻辑和数据结构表的总称
◦比如订单表 product_order_0、product_order_1、product_order_2,逻辑表就是product_order
分片键 (PartitionKey)
◦用于分片的数据库字段,是将数据库(表)水平拆分的关键字段
◦比如prouduct_order订单表,根据订单号 out_trade_no做哈希取模,则out_trade_no是分片键
◦除了对单分片字段的支持,ShardingSphere也支持根据多个字段进行分片
分片策略之行表达式分片策略
行表达式分片策略 InlineShardingStrategy
只支持【单分片键】使用Groovy的表达式,提供对SQL语句中的 =和IN 的分片操作支持
可以通过简单的配置使用,无需自定义分片算法,从而避免繁琐的Java代码开发
prouduct_order_$->{user_id % 8}` 表示订单表根据user_id模8,而分成8张表,表名称为prouduct_order_0`到`prouduct_order_7
通过实际举例代码加深下印象
下面需求来啦:
5G流量包模块中traffic表数据太多,在选取实际可用流量包时会影响性能,需要降低单表数据量,进行水平分表
未来2年,5G流量包平台累计5百万用户
付费流量包记录:一个用户10条/年,总量就是5千万条
单表不超过1千万数据,需要分5张表
进一步延伸,进行水平分表,比如 2张表、4张表、8张表、16张表
代码实现方式:
分表数量:线上分8张表,本地分2张表即可,(后续如果需要多个表,改下%后面数字即可)
分片key: account_no(用户登录账号),查询维度都是根据account_no进行查询
分片策略:行表达式分片策略 InlineShardingStrategy
新建表:traffic_0和traffic_1
CREATE TABLE `traffic_0` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`day_limit` int DEFAULT NULL COMMENT '每天限制多少个流量',
`day_used` int DEFAULT NULL COMMENT '当天用了多少个流量',
`account_no` bigint DEFAULT NULL COMMENT '账号',
`out_trade_no` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '订单号',
`expired_date` date DEFAULT NULL COMMENT '过期日期',
`product_id` bigint DEFAULT NULL COMMENT '商品主键',
`gmt_create` datetime DEFAULT CURRENT_TIMESTAMP,
`gmt_modified` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_trade_no` (`out_trade_no`,`account_no`) USING BTREE,
KEY `idx_account_no` (`account_no`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
pom.xml加入依赖包:
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.1.1</version>
</dependency>
配置文件更改:之前连接jdbc的配置都去掉
# 数据源 ds0 第一个数据库
shardingsphere:
datasource:
ds0:
connectionTimeoutMilliseconds: 30000
driver-class-name: com.mysql.cj.jdbc.Driver
idleTimeoutMilliseconds: 60000
jdbc-url: jdbc:mysql://120.79.xxx.xxx:3306/account表名称?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
maintenanceIntervalMilliseconds: 30000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 50
password: mysql密码
type: com.zaxxer.hikari.HikariDataSource
username: mysql用户名
names: ds0
props:
# 打印执行的数据库以及语句
sql:
show: true
sharding:
tables:
traffic:#traffic是逻辑表 当前配置是指的表位有0和1
# 指定traffic表的数据分布情况,配置数据节点,行表达式标识符使用 ${...} 或 $->{...},但前者与 Spring 本身的文件占位符冲突,所以在 Spring 环境中建议使用 $->{...}
actual-data-nodes: ds0.traffic_$->{0..1}
# 水平分表策略+行表达式分片
table-strategy:
inline:#根据用户账号取模,取到0和1
algorithm-expression: traffic_$->{account_no % 2}
sharding-column: account_no
测试工具类:
测试结果:
都正常入库啦 偶数在0表,基数在1表
到这就完成通过shardingjdbc指定字段取模分表啦