ShardingSphere水平分表策略配置和测试实战
-
概念
-
水平分表
-
把一个表的数据分到一个数据库的多张表中,每个表只有这个表的部分数据
-
核心是把一个大表,分割N个小表,每个表的结构是一样的,数据不一样,全部表的数据合起来就是全部数据
-
针对数据量巨大的单张表(比如订单表),按照某种规则(RANGE,HASH取模等),切分到多张表里面去
-
但是这些表还是在同一个库中,所以单数据库操作还是有IO瓶颈,主要是解决单表数据量过大的问题
-
减少锁表时间,没分表前,如果是DDL(create/alter/add等)语句,当需要添加一列的时候mysql会锁表,期间所有的读写操作只能等待
-
-
水平分表的适用场景
- 当一张表的数据达到几千万时,查询一次所花的时间长,需要进行优化,缩短查询时间
- 微博发送记录、微信消息记录、日志记录。以id增长或时间划分
- 网站签到等活动流水数据。以时间划分
- 当一张表的数据达到几千万时,查询一次所花的时间长,需要进行优化,缩短查询时间
-
实战样板
-
依赖引入
<dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> <version>4.1.1</version> </dependency>
-
application
# 数据源 ds0 第一个数据库 --- 版本:mysql8 shardingsphere: datasource: ds0: connectionTimeoutMilliseconds: 30000 driver-class-name: com.mysql.cj.jdbc.Driver idleTimeoutMilliseconds: 60000 jdbc-url: jdbc:mysql://[ip]:3306/[数据库]?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true maintenanceIntervalMilliseconds: 30000 maxLifetimeMilliseconds: 1800000 maxPoolSize: 50 minPoolSize: 50 password: [密码] type: com.zaxxer.hikari.HikariDataSource username: [用户名] names: ds0 props: # 打印执行的数据库以及语句 sql: show: true sharding: tables: [表名]: # 指定表的数据分布情况,配置数据节点,行表达式标识符使用 ${...} 或 $->{...},但前者与 Spring 本身的文件占位符冲突,所以在 Spring 环境中建议使用 $->{...} actual-data-nodes: ds0.[表名_]$->{0..1} # 水平分表策略+行表达式分片 table-strategy: inline: algorithm-expression: [表名_]$->{[取模字段] % 2} sharding-column: [取模字段]
-
测试
@Test public void testSaveTraffic(){ Random random = new Random(); for(int i=0;i<10;i++){ TrafficDO trafficDO = new TrafficDO(); // 设置取模字段的值 Int trafficDO.setAccountNo(Long.valueOf(random.nextInt(1000))); trafficMapper.insert(trafficDO); } }
-
结果分析
- 取模字段accountNo为偶数的对象,存储到traffic_0表
- 取模字段accountNo为奇数的对象,存储到traffic_1表
- 实现水平分表
- 缺陷: 主键id重复