ShardingSphere实战
前言
本文主要从sharding最新版本5.1.2版本入手搭建,按主键ID和时间进行分表。
本文主要介绍搭建过程,有兴趣了解shardingsphere的同学可以先自行查阅相关资料。
shardsphere官网:https://shardingsphere.apache.org/index_zh.html(建议下载master文档进行学习)
github地址:https://github.com/apache/shardingsphere.git
gitee地址:https://gitee.com/Sharding-Sphere/sharding-sphere.git
正文
这里搭建的框架采用 springboot2 + shardingsphere5 + mybatisplus(不用写sql) + mysql(druid连接池)
1、初始化SQL脚本(需要的自行前往文末项目地址获取)
● 示例中有user表和order表,user表按id分片,order表按时间进行年月分片。
● 注意:分表需要自行预创建,这里建议写个执行器创建
2、项目引入pom依赖(这里选的版本未发现冲突)

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>5.1.2</version>
</dependency> <dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.11</version>
</dependency>
maven依赖
3、进行yml配置
● 需要加上spring.shardingsphere.props.sql-show = true , 打印sharding执行的sql,便于观察理解分表的原理,生产环境可选择关闭。
● 这里主要是用order表根据年月进行分表,因考虑到需要兼容历史表,所以这里逻辑分表需包含历史表名,具体看配置项actual-data-nodes。
● 一般建议跨两个表进行查询,比如这里是按照月份分表,则建议限制查询时间跨度最大为一个月,这样最多跨两个逻辑分表进行查询,性能会提高很多。

spring:
application:
name: demo-shardingsphere
shardingsphere:
# 打印执行sql
props:
sql-show: true
# 数据源配置
datasource:
names: test
test:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ss_test?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
username: root
password: root
# 分片规则
rules:
sharding:
# 分片策略
sharding-algorithms:
# 自定义分片策略
order_inline:
type: class_based
props:
strategy: standard
algorithmClassName: com.demo.config.sharding.algorithm.OrderTableAlgorithm
tables:
# 需要进行分片的逻辑表名前缀
t_order:
# 逻辑分表
actual-data-nodes: test.t_order,test.t_order_$->{2022..2025}0$->{1..9},test.t_order_$->{2022..2025}1$->{0..2}
table-strategy:
standard:
# 分表的字段
sharding-column: create_date
# 自定义的分片策略名
sharding-algorithm-name: order_inline # 下面是按主键进行分表,规则比较简单,自定义表达式即可
# sharding-algorithms:
# user_inline:
# type: inline
# props:
# algorithm-expression: user_$->{id % 2}
# tables:
# user:
# actual-data-nodes: test.user_$->{0..1}
# table-strategy:
# standard:
# sharding-column: id
# sharding-algorithm-name: user_inline
# key-generate-strategy:
# column: id
# key-generator-name: snowflake
# key-generators:
# snowflake:
# type: SNOWFLAKE server:
port: 8889 # 定义跨表时间查询范围,小于min时间,则联查历史表,不允许大于max时间,具体可看自定义的分片策略实现
sharding:
table:
user:
base:
date:
min: 2022-08-01 00:00:00
max: 2023-01-31 23:59:59 #logging:
# level:
# com.demo.mapper: debug
配置文件
4、自定分片策略
● 这里采用jdk8的新时间特性LocalDateTime,需要与定义的分表字段类型对应上。
● sharding5使用了新的分片对象(5之前使用PreciseShargingAlgorithm),查询和插入都可以在一个对象里配置。
● 考虑到有些项目已经是在线上运行的项目,需要兼容历史表,这里配置中做了判断,需自行配置分表投产的时间作为区分,历史表数据不动,新数据采用分表插入和查询。

private static final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private static final DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("yyyyMM");
/**
* 获取查询对应分表名
* @param collection
* @param preciseShardingValue
* @return
*/
@Override
public String doSharding(Collection<String> collection, PreciseShardingValue<LocalDateTime> preciseShardingValue) {
LocalDateTime date = preciseShardingValue.getValue();
if (date == null) {
return collection.stream().findFirst().get();
}
String tableName = preciseShardingValue.getLogicTableName();
// 如果查询范围包括基础表,则需要联合基础表进行查询
LocalDateTime minBaseDate = LocalDateTime.parse(StaticValue.userBaseTableMinDate, dateFormatter);
if (date.isAfter(minBaseDate)) {
String tableSuffix = date.format(monthFormatter);
tableName = tableName.concat("_").concat(tableSuffix);
}
String t = tableName;
return collection.stream().filter(str -> str.equals(t)).findFirst().orElseThrow(() -> new RuntimeException(t + "分表不存在"));
}
/**
* 范围查询获取所有分表
*
* @param collection
* @param rangeShardingValue
* @return 分表集合
*/
@Override
public Collection<String> doSharding(Collection collection, RangeShardingValue rangeShardingValue) {
String logicTableName = rangeShardingValue.getLogicTableName();
Range<LocalDateTime> valueRange = rangeShardingValue.getValueRange();
Set<String> tableRange = extracted(logicTableName, valueRange.lowerEndpoint(), valueRange.upperEndpoint());
return tableRange;
}
/**
* 根据时间范围获取分表集合
*
* @param logicTableName
* @param lowerEndpoint
* @param upperEndpoint
* @return
*/
private Set<String> extracted(String logicTableName, LocalDateTime lowerEndpoint, LocalDateTime upperEndpoint) {
Set<String> rangeTable = new HashSet<>();
// 如果查询范围包括基础表,则需要联合基础表进行查询
LocalDateTime minBaseDate = LocalDateTime.parse(StaticValue.userBaseTableMinDate, dateFormatter);
LocalDateTime maxBaseDate = LocalDateTime.parse(StaticValue.userBaseTableMaxDate, dateFormatter);
if (lowerEndpoint.isBefore(minBaseDate)) {
lowerEndpoint = minBaseDate;
rangeTable.add(logicTableName);
}
if (upperEndpoint.isAfter(maxBaseDate)) {
throw new RuntimeException("结束时间不在当前时间内");
}
// 便利所有分表
while (lowerEndpoint.isBefore(upperEndpoint)) {
String tableName = logicTableName.concat("_").concat(lowerEndpoint.format(monthFormatter));
rangeTable.add(tableName);
lowerEndpoint = lowerEndpoint.plusMonths(1);
}
// 可能开始时间累加后与结束时间一致
String tableName = logicTableName.concat("_").concat(upperEndpoint.format(monthFormatter));
rangeTable.add(tableName);
return rangeTable;
}
5、自定义接口测试
● 接口定义请自行参考文末项目源码,这里直接上测试结果图
测试场景一:插入一条2022年10月份数据

sharding运行过程

执行结果,插入到表t_order_202210

测试场景二:范围查找2022-07-01至2022-12-01

sharding执行过程

执行结果,可以观察到我们刚插入的数据,另外一条是之前测试插入的

至此,本片文章结束,有兴趣的同学可以一起讨论,谢谢。
有兴趣可参考完整项目地址:https://gitee.com/yhc910/demo-shardingsphere
实战注意点(实时更新):
1、druid连接池属性,jdbc-url改为url
2、sharding-algorithm-name,注意algorithm后面不要加s,后面debug源码才找到问题
3、数据源配置url后面的属性,不要连着两个&&,不然会报错无效数组
ShardingSphere实战的更多相关文章
- 图灵学院JAVA互联网架构师专题学习笔记
图灵学院JAVA互联网架构师专题学习笔记 下载链接:链接: https://pan.baidu.com/s/1xbxDzmnQudnYtMt5Ce1ONQ 密码: fbdj如果失效联系v:itit11 ...
- ShardingSphere 集成 CosId 实战
背景 在软件系统演进过程中,随着业务规模的增长 (TPS/存储容量),我们需要通过集群化部署来分摊计算.存储压力. 应用服务的无状态设计使其具备了伸缩性.在使用 Kubernetes 部署时我们只需要 ...
- 数据量大了一定要分表,分库分表组件Sharding-JDBC入门与项目实战
最近项目中不少表的数据量越来越大,并且导致了一些数据库的性能问题.因此想借助一些分库分表的中间件,实现自动化分库分表实现.调研下来,发现Sharding-JDBC目前成熟度最高并且应用最广的Java分 ...
- Java实战:教你如何进行数据库分库分表
摘要:本文通过实际案例,说明如何按日期来对订单数据进行水平分库和分表,实现数据的分布式查询和操作. 本文分享自华为云社区<数据库分库分表Java实战经验总结 丨[绽放吧!数据库]>,作者: ...
- Apache ShardingSphere 在京东白条场景的落地之旅
京东白条使用 Apache ShardingSphere 解决了千亿数据存储和扩容的问题,为大促活动奠定了基础. 2014 年初,"京东白条"作为业内互联网信用支付产品,数据量爆发 ...
- DistSQL:像数据库一样使用 Apache ShardingSphere
Apache ShardingSphere 5.0.0-beta 深度解析的第一篇文章和大家一起重温了 ShardingSphere 的内核原理,并详细阐述了此版本在内核层面,特别是 SQL 能力方面 ...
- 重磅|Apache ShardingSphere 5.0.0 即将正式发布
Apache ShardingSphere 5.0.0 GA 版在经历 5.0.0-alpha 及 5.0.0-beta 接近两年时间的研发和打磨,终于将在 11 月份与大家正式见面! 11 月 10 ...
- 如何在 ShardingSphere 中开发自己的 DistSQL
在<DistSQL:像数据库一样使用 Apache ShardingSphere>和<SCTL 涅槃重生:投入 RAL 的怀抱>中,已经为大家介绍了 DistSQL 的设计初衷 ...
- ShardingSphere 云上实践:开箱即用的 ShardingSphere-Proxy 集群
本次 Apache ShardingSphere 5.1.2 版本更新为大家带来了三大全新功能,其中之一即为使用 ShardingSphere-Proxy chart 在云环境中快速部署一套 Shar ...
- ShardingSphere数据分片
码农在囧途 坚持是一件比较难的事,坚持并不是自欺欺人的一种自我麻痹和安慰,也不是做给被人的,我觉得,坚持的本质并没有带着过多的功利主义,如果满是功利主义,那么这个坚持并不会长久,也不会有好的收获,坚持 ...
随机推荐
- 洛谷P3374 【模板】树状数组 1-(单点修改,区间查询)
题目描述 如题,已知一个数列,你需要进行下面两种操作: 将某一个数加上 x 求出某区间每一个数的和 输入格式 第一行包含两个正整数 n,m,分别表示该数列数字的个数和操作的总个数. 第二行包含 n 个 ...
- Linux 文件系统inode号和备份恢复
目录 一.inode原理 二.时间类型 三.inode号管理 四.inode实验 五.备份恢复 七.备份实验 一.inode原理 inode只有一个,唯一的,一个文件必须占用一个inode号,但是至少 ...
- linux 账户和权限
目录 一.用户账户管理 二.组账号管理 三.用户账户文件和组账户文件 四.查询账户命令 五.设置目录与文件权限 六.设置命令与文件归属 七.默认文件属性umask 八.修改主机名 一.用户账户管理 u ...
- 前端八股文everybody准备好了没
引言 由于最近比较忙活没时间学习新东西,现在得空想着能不能好好整理出一些有用的东西,让记忆深刻一点,免得到时候实习找工作面试的时候一问三不知,也希望大家能指正出错误和对大家有点帮助,一起进步,加油奥里 ...
- Oracle rac环境的数据库导入操作记录
搞某一大项目的性能测试,将Oracle数据库dmp文件(211G)导入性能测试环境. 因为Oracle部署方式为rac,数据存储到共享磁盘.但由于对rac了解不足,这个过程中犯了两个错误: ① 表空间 ...
- ZYNQ 启动过程简介 以及 ZYNQ 裸机生成BOOT.BIN
背景 下图是ZYNQ的启动过程 上电复位等完成后,先执行BootRom,然后再根据MIO设定的启动方式选择对应从哪里启动,无论从哪里启动,都需要一个BOOT.BIN文件,对于裸机程序来说: BOOT. ...
- ASP.NET Core 6框架揭秘实例演示[39]:使用最简洁的代码实现登录、认证和注销
认证是一个确定请求访问者真实身份的过程,与认证相关的还有其他两个基本操作--登录和注销.ASP.NET Core利用AuthenticationMiddleware中间件完成针对请求的认证,并提供了用 ...
- 前端 vue 自定义导航栏组件高度及返回箭头 自定义 tabbar 图标
前端vue自定义导航栏组件高度及返回箭头 自定义tabbar图标, 下载完整代码请访问uni-app插件市场地址:https://ext.dcloud.net.cn/plugin?id=12986 效 ...
- ArcPy批量对大量遥感影像相减做差
本文介绍基于Python中ArcPy模块,对大量栅格遥感影像文件批量进行相减做差的方法. 首先,我们来明确一下本文的具体需求.现有一个存储有多张.tif格式遥感影像的文件夹,其中每一个遥感影像 ...
- G1垃圾回收参数调优及MySQL虚引用造成GC时间过长分析
1. 背景 我方有一应用,偶尔会出现GC时间过长(间隔约4小时),导致性能波动的问题(接口最长需要耗时3秒以上).经排查为G1垃圾回收器参数配置不当 叠加 MySQL 链接超过闲置时间回收,产生大量的 ...