大家好,我是工藤学编程 🦉一个正在努力学习的小博主,期待你的关注
实战代码系列最新文章😉C++实现图书管理系统(Qt C++ GUI界面版)
SpringBoot实战系列🐷【SpringBoot实战系列】Sharding-Jdbc实现分库分表到分布式ID生成器Snowflake自定义wrokId实战
环境搭建大集合环境搭建大集合(持续更新)
分库分表分库分表下的 ID 冲突问题与雪花算法讲解

前情摘要:

1、数据库性能优化
2、分库分表之优缺点分析
3、分库分表之数据库分片分类
4、分库分表之策略
5、分库分表技术栈讲解-Sharding-JDBC
6、分库分表下的 ID 冲突问题与雪花算法讲解

本文章目录

  • 分库分表之实战-sharding-JDBC
    • 一、SpringBoot2.5+MybatisPlus+Sharding-Jdbc项目创建
      • 1. 在创建好的Maven项目的pom文件中添加以下pom文件依赖:
      • 2. 创建对应测试的数据库表
      • 3、创建实体类以及对应数据库实体类
    • 二、 Sharding-Jdbc常规数据源配置和水平分表
      • 配置appliaction.properties
      • ShardingSphere SQL 执行日志解析
        • 1. Logic SQL(逻辑 SQL)
        • 2. Actual SQL(实际 SQL)
        • 3. 绑定参数(实际参数值)
        • 4. 分片路由逻辑分析
    • 三、分库分表下的 ID 冲突问题解决

分库分表之实战-sharding-JDBC

一、SpringBoot2.5+MybatisPlus+Sharding-Jdbc项目创建

1. 在创建好的Maven项目的pom文件中添加以下pom文件依赖:

<properties><java.version>11</java.version><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target><spring.boot.version>2.5.5</spring.boot.version><mybatisplus.boot.starter.version>3.4.0</mybatisplus.boot.starter.version><lombok.version>1.18.16</lombok.version><sharding-jdbc.version>4.1.1</sharding-jdbc.version><junit.version>4.12</junit.version><druid.version>1.1.16</druid.version><!--跳过单元测试--><skipTests>true</skipTests></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>${spring.boot.version}</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><version>${spring.boot.version}</version><scope>test</scope></dependency><!--mybatis plus和springboot整合--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>${mybatisplus.boot.starter.version}</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.27</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version></dependency><dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId><version>${sharding-jdbc.version}</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>${junit.version}</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>${spring.boot.version}</version><configuration><fork>true</fork><addResources>true</addResources></configuration></plugin></plugins></build>

2. 创建对应测试的数据库表

  • 新建数据库ccc_shop_order_0
CREATE DATABASE `ccc_shop_order_0` 
CHARACTER SET utf8mb4 
COLLATE utf8mb4_bin;
  • 新建数据库ccc_shop_order_1
CREATE DATABASE `ccc_shop_order_1` 
CHARACTER SET utf8mb4 
COLLATE utf8mb4_bin;
  • 在数据库ccc_shop_order_0中新建表product_order_0、product_order_1
 use ccc_shop_order_0;CREATE TABLE `product_order_0` (`id` bigint NOT NULL AUTO_INCREMENT,`out_trade_no` varchar(64) DEFAULT NULL COMMENT '订
单唯⼀标识',`state` varchar(11) DEFAULT NULL COMMENT 'NEW 未⽀
付订单,PAY已经⽀付订单,CANCEL超时取消订单',`create_time` datetime DEFAULT NULL COMMENT '订单⽣
成时间',`pay_amount` decimal(16,2) DEFAULT NULL COMMENT '订
单实际⽀付价格',`nickname` varchar(64) DEFAULT NULL COMMENT '昵称',`user_id` bigint DEFAULT NULL COMMENT '⽤户id',PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 
COLLATE=utf8mb4_bin;CREATE TABLE `product_order_1` (`id` bigint NOT NULL AUTO_INCREMENT,`out_trade_no` varchar(64) DEFAULT NULL COMMENT '订
单唯⼀标识',`state` varchar(11) DEFAULT NULL COMMENT 'NEW 未⽀
付订单,PAY已经⽀付订单,CANCEL超时取消订单',`create_time` datetime DEFAULT NULL COMMENT '订单⽣
成时间',`pay_amount` decimal(16,2) DEFAULT NULL COMMENT '订
单实际⽀付价格',`nickname` varchar(64) DEFAULT NULL COMMENT '昵称',`user_id` bigint DEFAULT NULL COMMENT '⽤户id',PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 
COLLATE=utf8mb4_bin;
  • 在数据库ccc_shop_order_1中新建表product_order_0、product_order_1
use ccc_shop_order_1;CREATE TABLE `product_order_0` (`id` bigint NOT NULL AUTO_INCREMENT,`out_trade_no` varchar(64) DEFAULT NULL COMMENT '订
单唯⼀标识',`state` varchar(11) DEFAULT NULL COMMENT 'NEW 未⽀
付订单,PAY已经⽀付订单,CANCEL超时取消订单',`create_time` datetime DEFAULT NULL COMMENT '订单⽣
成时间',`pay_amount` decimal(16,2) DEFAULT NULL COMMENT '订
单实际⽀付价格',`nickname` varchar(64) DEFAULT NULL COMMENT '昵称',`user_id` bigint DEFAULT NULL COMMENT '⽤户id',PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 
COLLATE=utf8mb4_bin;CREATE TABLE `product_order_1` (`id` bigint NOT NULL AUTO_INCREMENT,`out_trade_no` varchar(64) DEFAULT NULL COMMENT '订
单唯⼀标识',`state` varchar(11) DEFAULT NULL COMMENT 'NEW 未⽀
付订单,PAY已经⽀付订单,CANCEL超时取消订单',`create_time` datetime DEFAULT NULL COMMENT '订单⽣
成时间',`pay_amount` decimal(16,2) DEFAULT NULL COMMENT '订
单实际⽀付价格',`nickname` varchar(64) DEFAULT NULL COMMENT '昵称',`user_id` bigint DEFAULT NULL COMMENT '⽤户id',PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 
COLLATE=utf8mb4_bin;

3、创建实体类以及对应数据库实体类

ProductOrderDO

@Data
@EqualsAndHashCode(callSuper = false)
@TableName("product_order")
public class ProductOrderDO {@TableId(value = "id", type = IdType.AUTO)private Long id;private String outTradeNo;private String state;private Date createTime;private Double payAmount;private String nickname;private Long userId;
}

ProductOrderMapper

public interface ProductOrderMapper extendsBaseMapper<ProductOrderDO> {
}

目前我的工程如下,大家可以对比一下
在这里插入图片描述

二、 Sharding-Jdbc常规数据源配置和水平分表

配置appliaction.properties

spring.application.name=ccc-sharding-jdbc
server.port=8080
# 打印执⾏的数据库以及语句
spring.shardingsphere.props.sql.show=true
# 数据源 db0,如果有多个用逗号分隔,有多少个,下面具体数据库就要配置多少个
spring.shardingsphere.datasource.names=ds0,ds1
# 第⼀个数据库
spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds0.jdbc-url=jdbc:mysql://127.0.0.1:3306/ccc_shop_order_0?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
spring.shardingsphere.datasource.ds0.username=root
spring.shardingsphere.datasource.ds0.password=123456# 第二个数据库
spring.shardingsphere.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds1.jdbc-url=jdbc:mysql://127.0.0.1:3306/ccc_shop_order_1?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
spring.shardingsphere.datasource.ds1.username=root
spring.shardingsphere.datasource.ds1.password=123456# 指定product_order表的数据分布情况,配置数据节点,⾏表达式标识符使⽤ ${...} 或 $->{...},但前者与 Spring 本身的⽂件占位符冲突,所以在 Spring 环境中建议使⽤ $->{...}
spring.shardingsphere.sharding.tables.product_order.actual-data-nodes=ds0.product_order_$->{0..1}
# 指定product_order表的分⽚策略,分⽚策略包括【分⽚键和分⽚算法】
spring.shardingsphere.sharding.tables.product_order.table-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.product_order.table-strategy.inline.algorithm-expression=product_order_$->{user_id % 2}

这里我们使用的是mysql8.0

  1. spring.shardingsphere.datasource.ds0.password=123456 这里大家记得修改为自己数据库的密码
  2. spring.shardingsphere.datasource.ds0.jdbc-url=jdbc:mysql://127.0.0.1:3306/ccc_shop_order_0?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true 这里大家记得把ip改为自己的安排(如果数据库不在本地)

ShardingSphere SQL 执行日志解析

编写单元测试DbTest

@RunWith(SpringRunner.class)  //底层⽤junitSpringJUnit4ClassRunner
@SpringBootTest(classes = DemoApplication.class)
@Slf4j
public class DbTest {@Autowiredprivate ProductOrderMapper productOrderMapper;@Testpublic void testSaveProductOrder(){for(int i=0;i<10;i++){ProductOrderDO productOrder = new ProductOrderDO();productOrder.setCreateTime(new Date());productOrder.setNickname("ccc_i="+i);productOrder.setOutTradeNo(UUID.randomUUID().toString().substring(0,32));productOrder.setPayAmount(100.00);productOrder.setState("PAY");productOrder.setUserId(Long.valueOf(i+""));productOrderMapper.insert(productOrder);}}
}

执行结果如下
在这里插入图片描述

我们查看控制台输出,展示了从逻辑 SQL 到实际 SQL 的路由过程。我来逐行解释:

1. Logic SQL(逻辑 SQL)
INSERT INTO product_order (out_trade_no, state, create_time, pay_amount, nickname, user_id) 
VALUES (?, ?, ?, ?, ?, ?)

这是应用程序实际执行的 SQL 语句:

  • 操作对象:product_order 表(逻辑表名)
  • 参数占位符:? 代表实际参数会在执行时传入
2. Actual SQL(实际 SQL)
ds0 ::: INSERT INTO product_order_0 (out_trade_no, state, create_time, pay_amount, nickname, user_id) 
VALUES (?, ?, ?, ?, ?, ?)

这是 ShardingSphere 根据分片规则路由后实际执行的 SQL:

  • ds0:目标数据源(数据库实例)
  • product_order_0:物理表名
  • 可以看到,逻辑表 product_order 被路由到了物理表 product_order_0
3. 绑定参数(实际参数值)
::: [d861e3e2-720a-4d16-bb67-12f96d31, PAY, 2025-06-30 16:24:23.075, 100.0, ccc_i=0, 0]

这些是占位符 ? 对应的实际参数值:

  1. out_trade_no: d861e3e2-720a-4d16-bb67-12f96d31(交易号)
  2. state: PAY(支付状态)
  3. create_time: 2025-06-30 16:24:23.075(创建时间)
  4. pay_amount: 100.0(支付金额)
  5. nickname: ccc_i=0(用户昵称)
  6. user_id: 0(用户ID,分片键)
4. 分片路由逻辑分析

根据我们之前的配置:

spring.shardingsphere.sharding.tables.product_order.table-strategy.inline.algorithm-expression=product_order_$->{user_id % 2}

user_id=0 时:

  • 0 % 2 = 0 → 路由到 product_order_0
  • 所以这条记录被写入 ds0 库的 product_order_0

三、分库分表下的 ID 冲突问题解决

在 分库分表下的 ID 冲突问题与雪花算法讲解中,我们提到了,同时我们前面的结果表明使用的时候,也确实存在ID冲突问题。因此我们需要使用雪花算法解决这个问题。

  • 方式⼀
    订单id使用MybatisPlus的配置,ProductOrder类配置@TableId(value = “id”, type = IdType.ASSIGN_ID)默认实现类为DefaultIdentifierGenerator雪花算法
    在这里插入图片描述
  • 方式⼆
    使⽤Sharding-Jdbc配置⽂件,注释DO类里面的id分配策略
spring.shardingsphere.sharding.tables.product_order.key-generator.column=idspring.shardingsphere.sharding.tables.product_order.key-generator.type=SNOWFLAKE

这里我使用的是方式2,让我们再重新运行测试函数,查看结果
在这里插入图片描述

觉得有用请点赞收藏!
如果有相关问题,欢迎评论区留言讨论~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/87365.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/87365.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/87365.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

httpcore-nio引起的线程、fd泄露问题

依赖来源&#xff1a;httpasyncclient-4.1.4.jar 现象 程序报错too many open files 线程数飙升、句柄数飙升 thread dump显示大量 "I/O dispatcher 7215" #9102 prio5 os_prio0 tid0x00002b7ba036a800 nid0x6f24 runnable [0x00002b7d98d41000]java.lang.Thread.…

多线程生产者消费者模型实战案例

多线程生产者消费者模型实战案例 前言业务场景术前准备无锁无事务有事务 synchronized事务在锁外事务在锁内 数据库行锁什么是数据库行锁有事务没有事务 乐观锁ReentrantLock分布式锁 前言 曾经一直有一个疑惑&#xff0c;就是关于多线程生产者消费者模型的学习过程中&#xf…

青少年编程与数学 02-022 专业应用软件简介 03 三维建模及动画软件:Autodesk Maya

青少年编程与数学 02-022 专业应用软件简介 03 三维建模及动画软件&#xff1a;Autodesk Maya 一、什么是三维建模二、什么是计算机动画三、三维建模及动画设计软件的发展历程&#xff08;一&#xff09;早期探索阶段&#xff08;20世纪60年代 - 80年代&#xff09;&#xff08…

获得 OCM 大师证书学习历练

当我站在山城重庆的洪崖洞前&#xff0c;看着璀璨的夜景倒映在嘉陵江上&#xff0c;手中紧握着 OCM 大师证书&#xff0c;那一刻&#xff0c;备考时的艰辛与考试时的紧张都化作了满满的成就感。这段在重庆获得 OCM 大师证书的经历&#xff0c;就像一场充满挑战与惊喜的冒险&…

srs-gb28181 与 SRS 5.0 对 GB28181 国标支持

srs-gb28181 是基于 SRS 4.0/5.0 的国标&#xff08;GB28181&#xff09;扩展分支&#xff0c;而 SRS 5.0 官方版本也逐步增强了对 GB28181 的支持。以下是两者的主要区别&#xff1a; 1. 功能支持对比 功能srs-gb28181&#xff08;扩展分支&#xff09;SRS 5.0&#xff08;官…

算法第18天|继续二叉树:修剪二叉搜索树、将有序数组转化为二叉搜索树、把二叉搜索树转换为累加树

今日总结&#xff1a; 1、修剪二叉搜索树&#xff08;重点思考如何修剪&#xff09; &#xff08;1&#xff09;递归的返回值是什么&#xff1f;&#xff08;与插入、删除一样&#xff09; &#xff08;2&#xff09;递归的单层逻辑一定要缕清&#xff08;3中情况讨论&#xff…

C# 多线程(三)线程池

目录 1.通过TPL使用线程池 2.不使用TPL进入线程池的办法 异步委托 3.线程池优化技术 最小线程数的工作原理 每当启动一个新线程时&#xff0c;系统都需要花费数百微秒来分配资源&#xff0c;例如创建独立的局部变量栈空间。默认情况下&#xff0c;每个线程还会占用约1…

学习笔记(29):训练集与测试集划分详解:train_test_split 函数深度解析

学习笔记(29):训练集与测试集划分详解&#xff1a;train_test_split 函数深度解析 一、为什么需要划分训练集和测试集&#xff1f; 在机器学习中&#xff0c;模型需要经历两个核心阶段&#xff1a; 训练阶段&#xff1a;用训练集数据学习特征与目标值的映射关系&#xff08;…

【全网唯一】自动化编辑器 Windows版纯本地离线文字识别插件

目的 自动化编辑器超轻量级RPA工具&#xff0c;零代码制作RPA自动化任务&#xff0c;解放双手&#xff0c;释放双眼&#xff0c;轻松玩游戏&#xff0c;刷任务。本篇文章主要讲解下自动化编辑器的TomatoOCR纯本地离线文字识别Windows版插件如何使用和集成。 准备工作 1、下载自…

GitHub 2FA绑定

GitHub 2FA绑定 作为全球最大的代码托管平台&#xff0c;GitHub对账号安全的重视程度不断提升——自2023年3月起&#xff0c;GitHub已要求所有在GitHub.com上贡献代码的用户必须启用双因素身份验证&#xff08;2FA&#xff09;。如果你是符合条件的用户&#xff0c;会收到一封…

pytest fixture基础大全详解

一、介绍 作用 fixture主要有两个作用&#xff1a; 复用测试数据和环境&#xff0c;可以减少重复的代码&#xff1b;可以在测试用例运行前和运行后设置和清理资源&#xff0c;避免对测试结果产生影响&#xff0c;同时也可以提高测试用例的运行效率。 优势 pytest框架的fix…

Unity知识点-Renderer常用材质变量

本篇总结了Unity中renderer的3种常用的材质相关的变量&#xff1a;renderer.material,renderer.sharedMaterial,renderer.MaterialPropertyBlock。以及三者对SRPBatcher的影响。 一.介绍及对比 1.概念介绍 1.material 定义&#xff1a;material 是Render组件&#xff08;如…

【算法】​​如何判断时间复杂度?

文章目录 1. 什么是时间复杂度&#xff1f;为什么需要时间复杂度&#xff1f; 2. 常见时间复杂度对比3. 如何分析时间复杂度&#xff1f;&#xff08;Java版&#xff09;&#x1f539; 步骤1&#xff1a;找出基本操作&#x1f539; 步骤2&#xff1a;分析循环结构&#xff08;1…

MySQL使用C语言连接

文章目录 版本查看以及编译mysql接口介绍初始化链接数据库下发mysql命令mysql_query获取执行结果mysql_store_result获取结果行数mysql_num_rows获取结果列数mysql_num_fields获取列名mysql_fetch_fields获取结果内容mysql_fetch_row关闭mysql链接mysql_closeC语言操作mysql查看…

坚持每日Codeforces三题挑战:Day 7 - 题目详解(2025-06-11,难度:1200,1300,1500)

每天坚持写三道题第七天&#xff1a; Problem - A - Codeforces 1200 Problem - B - Codeforces 1300 Problem - A - Codeforces 1500 目录 题目一: 题目大意: 解题思路: 代码(C): 题目二: 题目大意: 解题思路: 代码(C): 题目三: 题目大意: 解题思路: 代码(C): …

洛谷 P4305:[JLOI2011] 不重复数字 ← unordered_set

【题目来源】 https://www.luogu.com.cn/problem/P4305 【题目描述】 给定 n 个数&#xff0c;要求把其中重复的去掉&#xff0c;只保留第一次出现的数。 【输入格式】 第一行一个整数 T&#xff0c;表示数据组数。 对于每组数据&#xff0c;第一行一个整数 n。第二行 n 个数…

STM32固件升级设计——SPIFLASH模拟U盘升级固件

目录 概述 一、功能描述 1、BootLoader部分&#xff1a; 2、APP部分&#xff1a; 二、BootLoader程序制作 1、分区定义 2、 主函数 3、配置USB 4、配置fatfs文件系统 5、程序跳转 三、APP程序制作 四、工程配置&#xff08;默认KEIL5&#xff09; 五、运行测试 六…

解锁阿里云日志服务SLS:云时代的日志管理利器

引言&#xff1a;开启日志管理新篇 在云计算时代&#xff0c;数据如同企业的血液&#xff0c;源源不断地产生并流动。从用户的每一次点击&#xff0c;到系统后台的每一个操作&#xff0c;数据都在记录着企业运营的轨迹。而在这些海量的数据中&#xff0c;日志数据占据着至关重…

Keye-VL-8B-Preview:由快手 Kwai Keye 团队精心打造的尖端多模态大语言模型

&#x1f525; News 2025.06.26 &#x1f31f; 我们非常自豪地推出Kwai Keye-VL&#xff0c;这是快手Kwai Keye团队精心打造的前沿多模态大语言模型。作为快手先进技术生态中的核心AI产品&#xff0c;Keye在视频理解、视觉感知和推理任务方面表现卓越&#xff0c;树立了新的性…

Web前端之JavaScript实现图片圆环、圆环元素根据角度指向圆心、translate、rotate

MENU 前言效果HtmlStyleJavaScript 前言 代码段创建了一个由6个WiFi图标组成的圆形排列&#xff0c;每个图标均匀分布在圆周上。 效果 Html 代码 <div class"ring"><div class"item"><img class"img" src"../image/icon/W…