目录

一、背景

二、优化事项

三、具体实战

四、遇到的问题

五、项目源码地址


一、背景

最近在公司手头上的项目单表达到了五千万的规模,而且日增长量每天就有10w左右,一个月就有大概300w的数据,这样一直下去过几个月以后表的数据很容易就上亿了,这样不利于管理以及在大表的情况下,对于表的DDL效率也会相对下降,和几个同事商量了下,于是乎开始做分表的技术优化。

二、优化事项

(1)首先先确定使用场景,当前表的使用场景更多的是根据一个具体的标识值去查询,范围查询的场景频率相对低下,在这这种情况下考虑想标识值作为分片键去进行分表。                              具体的算法为:通过标识值通过算法算出具体的时间季度,按季节进行拆分进行拆分,也就是一年

record_delivery_log

4个表record_order_log_202101,record_order_log_202102,record_order_log_202103,record_order_log_202104

拆分前单表数据量为 5000w

拆分后单表的数据量变成1200w,能够容忍将来4~ 5倍的增长量,符合预期范围。

(2)调研了对应的分库分表中间件,目前Sharing-jdbc是最主流的中间件,而且社区和文档较完善,故采用Sharing-jdbc作为分表的中间件。

三、具体实战

在这里因为公司项目不好复用的原因,用一个模拟项目来模拟这次改造。

(1)参照sharing-jdbc文档对项目进行改造

引入sharing-jdbc对应的pom。

 <dependency><groupId>org.apache.shardingsphere</groupId><artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId><version>5.0.0-beta</version></dependency>

对应的配置文件

#端口
server.port=8080# 数据源ds0
spring.shardingsphere.datasource.name=ds0
# 数据源ds0的配置
spring.shardingsphere.datasource.ds0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.ds0.driverClassName=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds0.url=jdbc:mysql://localhost:3306/world1?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2b8
spring.shardingsphere.datasource.ds0.username=root
spring.shardingsphere.datasource.ds0.password=123456# 分片规则,这里只分表,所以仅指定表的分片规则
spring.shardingsphere.rules.sharding.tables.record_order_log.actual-data-nodes=ds0.record_order_log_$->{2021..2031}0$->{1..4}# 指定数据库的分片键,只有一个库所以还是用分表的分片键
spring.shardingsphere.rules.sharding.tables.record_order_log.database-strategy.standard.sharding-column=order_delivery_id
spring.shardingsphere.rules.sharding.tables.record_order_log.database-strategy.standard.sharding-algorithm-name=database-inline# 指定分表的分片键
spring.shardingsphere.rules.sharding.tables.record_order_log.table-strategy.standard.sharding-column=order_delivery_id
spring.shardingsphere.rules.sharding.tables.record_order_log.table-strategy.standard.sharding-algorithm-name=table-inline# Omit t_order_item table rule configuration ...
# ...# 分片规则(默认取模)
spring.shardingsphere.rules.sharding.sharding-algorithms.database-inline.type=INLINE
spring.shardingsphere.rules.sharding.sharding-algorithms.database-inline.props.algorithm-expression=ds0
spring.shardingsphere.rules.sharding.sharding-algorithms.table-inline.type=CLASS_BASED
spring.shardingsphere.rules.sharding.sharding-algorithms.table-inline.props.strategy=STANDARD
spring.shardingsphere.rules.sharding.sharding-algorithms.table-inline.props.algorithmClassName=com.cus.shd.sharingjdbc.config.OrderDeliveryIdShardingAlgorithm
spring.shardingsphere.props.sql.show=true#mybatis-plus??
mybatis-plus.mapper-locations=classpath:mappers/*.xml
mybatis-plus.type-aliases-package=com.cus.shd.sharingjdbc.model
mybatis-plus.configuration.map-underscore-to-camel-case=true
# sql??
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl#本地数据库链接,忽略了springboot自动加载后失效
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/world1?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2b8
spring.datasource.username=root
spring.datasource.password=123456

注意好分表键设置时候的表名。

(2)自定义分片键策略,根据order_delivery_id按季度进行存储

package com.cus.shd.sharingjdbc.config;import org.apache.commons.lang.StringUtils;
import org.apache.shardingsphere.sharding.api.sharding.ShardingAutoTableAlgorithm;
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Collection;/*** @author ASUS* @Description 自定义分片策略* @Date 2021/11/6 22:20**/public class OrderDeliveryIdShardingAlgorithm implements StandardShardingAlgorithm<Long> {@Overridepublic String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {String orderDeliveryId = shardingValue.getValue().toString();orderDeliveryId = orderDeliveryId.substring(0,orderDeliveryId.length() - 4);// 将时间戳转为当前时间LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(Long.valueOf(orderDeliveryId)/1000, 0, ZoneOffset.ofHours(8));String availableTargetName;int month = localDateTime.getMonthValue();LocalDateTime nowTime = LocalDateTime.now();int year = nowTime.getYear();if(month >= 1 && month < 3){availableTargetName = "01";}else if(month >= 3 && month < 6){availableTargetName = "02";}else if(month >= 6 && month < 9){availableTargetName = "03";}else {availableTargetName = "04";}if(StringUtils.isEmpty(availableTargetName)){return null;}return String.format("%s_%s%s",shardingValue.getLogicTableName(),year,availableTargetName);}@Overridepublic Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Long> shardingValue) {return availableTargetNames;}@Overridepublic void init() {}@Overridepublic String getType() {return "ORDER_DELIVERY_ID";}
}

(3)模拟提供两个接口,一个按id查询,一个插入接口。(修改的场景暂时没有,所以不考虑)

新增的时候做了模拟插入,能够根据分片算法将数据存储到对应的表,达到效果。

查询同理。

(4)sharing-jdbc 不会自动的进行创建表,所以需在后台维护一个定时任务,到了一定的季度点就要进行建表操作。(需确保生产环境的应用程序对应的数据库账号是否有建表权限)

<update id="createNewTable" parameterType="String">CREATE TABLE ${tableName} SELECT * FROM record_order_log WHERE 1=2</update>

四、遇到的问题

1、引入sharing-jdbc包的时候报错了。这里debug到源码发现是mybatisPlus的自动启动器(MybatisPlusAutoConfiguration)有指定单一数据源类(spring中数据源不能有多个实现类)的时候才会启动,因为sharing的引入造成了多数据源(多datasource),所以这个就不会启动了,导致了实例化mapper的时候报错了。解决方案是在SpringBoot的启动类的注解加上

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class,DruidDataSourceAutoConfigure.class})

忽略掉SpringBoot数据源自动装配以及Druid数据源的自动装配,把所有的数据源实例化交给sharing-jdbc

2、部分项目存在历史遗留的问题,如果是mybatis或者hibernate的情况下,不想彻底引入sharding-jdbc数据源的话,个人觉得可以使用多数据源的形式来进行改造,去扩展需要使用分表的一些数据库操作,切换对应的sharding数据源进行数据库操作。具体可以参考switchDataSource目录下的一些切换数据源的代码。

3、给自己的疑问

忽略了DataSourceAutoConfiguration.class后,sharing-jdbc是如何整合mybatis-plus的?

答:其实也不难,相当于数据源这个对象原本由SpringBoot自带的数据源自动注入进行注入,现在换成了Sharding的自动装配(ShardingSphereAutoConfiguration)来进行注入,相当于换了整个数据源的一套东西,用的也是sharding整套的东西。

所以在改造的时候需要检查一下是否对旧的项目存在影响。

五、项目源码地址

cus-sharding-jdbc: sharding-jdbc springboot实战

ShardingJDBC实战相关推荐

  1. Sharding-JDBC 实战(史上最全)

    文章很长,而且持续更新,建议收藏起来,慢慢读! Java 高并发 发烧友社群:疯狂创客圈(总入口) 奉上以下珍贵的学习资源: 免费赠送 经典图书 : 极致经典 + 社群大片好评 < Java 高 ...

  2. 【ShardingSphere技术专题】「ShardingJDBC实战阶段」SpringBoot之整合ShardingJDBC实现分库分表(JavaConfig方式)

    前提介绍 ShardingSphere介绍 ShardingSphere是一套开源的分布式数据库中间件解决方案组成的生态圈,它由Sharding-JDBC.Sharding-Proxy和Shardin ...

  3. Sharding-JDBC(一)SpringBoot集成

    目录 1.背景 2.简介 3.依赖与配置 4.表结构(1..3) 5.测试验证 5.1 批量保存 5.2 列表查询 6.源码地址 1.背景 随着业务数据量的增加,原来所有的数据都是在一个数据库上,网络 ...

  4. MySQL多数据源笔记5-ShardingJDBC实战

    MySQL多数据源笔记5-ShardingJDBC实战 Sharding-JDBC集分库分表.读写分离.分布式主键.柔性事务和数据治理与一身,提供一站式的解决分布式关系型数据库的解决方案. 从2.x版 ...

  5. Sharding-jdbc

    前言 课程目标 掌握 Sharding-JDBC 的使用方式 掌握分布式事务.全局 ID 等问题的解决方案 理解 Sharding-JDBC 的工作流程和实现原理 理解基于 Mycat 和 Shard ...

  6. 分库分表Sharding-JDBC最佳实践专题

    一 Mysql数据库架构演变历史 单机 请求量大查询慢 单机故障导致业务不可用 主从 数据库主从同步,从库可以水平扩展,满足更大读需求 但单服务器TPS,内存,IO都是有限的 双主 用户量级上来后,写 ...

  7. 当你的Stream遇上Lambda就爱上了,超级无敌酷酷 - 第418篇

    历史文章(累计400+篇文章) <国内最全的Spring Boot系列之一> <国内最全的Spring Boot系列之二> <国内最全的Spring Boot系列之三&g ...

  8. Spring Boot使用ApplicationEvent来实现事件发布订阅功能(美女一个都不能少,都要通知到) - 第420篇

    历史文章(累计400+篇文章) <国内最全的Spring Boot系列之一> <国内最全的Spring Boot系列之二> <国内最全的Spring Boot系列之三&g ...

  9. Apache ShardingSphere(二) 基本使用

    文章目录 二 ShardingSphere JDBC 基本使用 2.1 ShardingSphere JDBC 水平分表 2.1.1 案例入门 2.1.2 解读配置文件 2.1.3 其他测试 2.1. ...

最新文章

  1. TensorRT C++ 批量推理笔记
  2. 化工热力学补考成功,几天没有头脑了,赶紧赏自己几题Leetcode动态规划算法最长系列
  3. Hbase之protobuf的使用
  4. python像素处理_Python+OpenCV图像处理(五)—— 像素运算
  5. Github | PyTorch实现的深度强化学习算法集
  6. JupyterNotebook设置并切换不同Python启动环境
  7. 西瓜书+实战+吴恩达机器学习(九)监督学习之k近邻 K-Nearest Neighbor
  8. object 整理中..... 顶级页面
  9. python使用梯度下降方法实现线性回归算法_python实现线性回归梯度下降算法
  10. 第三季-第6课-静态函数库设计
  11. vue vant ui 教程注意事项
  12. AI赋能,使用客服机器人改善客户服务的几种方法
  13. 2010-2019年款北汽原厂维修手册电路图线路图资料下载
  14. 3大领域,4大方向,做好数据分析岗位的职业规划
  15. lpx寒假作业案例5
  16. 2021智能零售领域最具商业合作价值企业盘点
  17. 马斯克要将特斯拉汽车送上火星,还要将《太空怪人》作为背景音乐
  18. python是否高送转预测股票_A股 最新2019年报高送转预期和业绩翻倍股一览!(附表)...
  19. 大阪第8天——论日本的脱鞋文化(一家之言不收板砖)
  20. Shell中#*/和%/*是什么意思?

热门文章

  1. 第13期5G消息云课堂大咖分享|联动云通信副总裁王鹏
  2. MMP7人源全长重组蛋白说明书
  3. 河南省专升本考试技巧与选择题
  4. 做外贸SOHO如何收汇
  5. golang-ants协程池使用和实现逻辑
  6. Qt应用程序“xxx.exe 已停止工作 故障模块msvcr120.dll”
  7. 大企业纷纷裁员,北森、宜员科技们的HR生意还好做吗?
  8. Android 音频——PCM转WAV
  9. mysql 查询每张表的数据量
  10. Torch 池化操作大全 MaxPool2d MaxUnpool2d AvgPool2d FractionalMaxPool2d LPPool2d AdaptivePool2d dilation详解