分庫分表之實戰-sharding-JDBC

大家好,我是工藤學編程 🦉一個正在努力學習的小博主,期待你的關注
實戰代碼系列最新文章😉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…