這是一個或許對你有用的社群
《專案實戰(影片)》:從書中學,往事上“練” 《網際網路高頻面試題》:面朝簡歷學習,春暖花開 《架構 x 系統設計》:摧枯拉朽,掌控面試高頻場景題 《精進 Java 學習指南》:系統學習,網際網路主流技術棧 《必讀 Java 原始碼專欄》:知其然,知其所以然
這是一個或許對你有用的開源專案
國產 Star 破 10w+ 的開源專案,前端包括管理後臺 + 微信小程式,後端支援單體和微服務架構。功能涵蓋 RBAC 許可權、SaaS 多租戶、資料許可權、商城、支付、工作流、大屏報表、微信公眾號、ERP、CRM、AI 大模型等等功能:
Boot 多模組架構:https://gitee.com/zhijiantianya/ruoyi-vue-pro Cloud 微服務架構:https://gitee.com/zhijiantianya/yudao-cloud 影片教程:https://doc.iocoder.cn 【國內首批】支援 JDK 17/21 + SpringBoot 3.3、JDK 8/11 + Spring Boot 2.7 雙版本

1. 全域性唯一 ID 問題
問題描述
-
訂單表_1
的主鍵從 1 開始,訂單表_2
的主鍵也從 1 開始。 -
在需要全域性唯一 ID 的場景(如訂單號、使用者 ID)中會發生衝突。
解決方案
1.1 使用分散式 ID 生成器
推薦工具:
-
Snowflake :Twitter 開源的分散式 ID 演算法。 -
百度 UidGenerator :基於 Snowflake 的改進版。 -
Leaf :美團開源,號段模式和 Snowflake 雙支援。
程式碼示例:Snowflake 演算法
publicclassSnowflakeIdGenerator
{
privatefinallong
epoch =
1622476800000L
;
// 自定義時間戳
privatefinallong
workerIdBits =
5L
;
// 機器ID
privatefinallong
datacenterIdBits =
5L
;
// 資料中心ID
privatefinallong
sequenceBits =
12L
;
// 序列號
privatefinallong
maxWorkerId = ~(-
1L
<< workerIdBits);
privatefinallong
maxDatacenterId = ~(-
1L
<< datacenterIdBits);
privatefinallong
sequenceMask = ~(-
1L
<< sequenceBits);
privatelong
workerId;
privatelong
datacenterId;
privatelong
sequence =
0L
;
privatelong
lastTimestamp = -
1L
;
publicSnowflakeIdGenerator(long workerId, long datacenterId)
{
if
(workerId > maxWorkerId || workerId <
0
)
thrownew
IllegalArgumentException(
"Worker ID out of range"
);
if
(datacenterId > maxDatacenterId || datacenterId <
0
)
thrownew
IllegalArgumentException(
"Datacenter ID out of range"
);
this
.workerId = workerId;
this
.datacenterId = datacenterId;
}
publicsynchronizedlongnextId()
{
long
timestamp = System.currentTimeMillis();
if
(timestamp < lastTimestamp)
thrownew
RuntimeException(
"Clock moved backwards"
);
if
(timestamp == lastTimestamp) {
sequence = (sequence +
1
) & sequenceMask;
if
(sequence ==
0
) timestamp = waitNextMillis(lastTimestamp);
}
else
sequence =
0L
;
lastTimestamp = timestamp;
return
((timestamp - epoch) << (workerIdBits + datacenterIdBits + sequenceBits))
| (datacenterId << (workerIdBits + sequenceBits))
| (workerId << sequenceBits)
| sequence;
}
privatelongwaitNextMillis(long lastTimestamp)
{
long
timestamp = System.currentTimeMillis();
while
(timestamp <= lastTimestamp) timestamp = System.currentTimeMillis();
return
timestamp;
}
}
1.2 資料庫號段分配
-
原理 :維護一個獨立的
global_id
表,分庫按步長分配 ID: -
庫 1:ID 步長為 2,從 1 開始(1, 3, 5…)。 -
庫 2:ID 步長為 2,從 2 開始(2, 4, 6…)。
示例
CREATE TABLE
global_id
(
id INT PRIMARY KEY AUTO_INCREMENT,
stub CHAR(
1
)
NOT NULL UNIQUE
)
;
-- 步長設定:
SET @
@auto
_increment_increment =
2
;
SET @
@auto
_increment_offset =
1
;
基於 Spring Boot + MyBatis Plus + Vue & Element 實現的後臺管理系統 + 使用者小程式,支援 RBAC 動態許可權、多租戶、資料許可權、工作流、三方登入、支付、簡訊、商城等功能
專案地址:https://github.com/YunaiV/ruoyi-vue-pro 影片教程:https://doc.iocoder.cn/video/
2. 跨庫跨表查詢複雜性
問題描述
-
查詢所有訂單總數,需要跨 10 個訂單表聚合。 -
按建立時間分頁查詢所有訂單。
解決方案
2.1 使用中介軟體(推薦)
-
ShardingSphere 或 MyCAT :支援 SQL 分片執行和結果合併。 -
優點:業務程式碼無需修改,中介軟體完成分庫分表邏輯。
2.2 手動分片查詢
-
按分片逐一查詢資料,在業務層合併結果。
示例程式碼:聚合查詢
publicintcountAllOrders()
{
int
total =
0
;
for
(String db : List.of(
"db1"
,
"db2"
,
"db3"
)) {
String sql =
"SELECT COUNT(*) FROM "
+ db +
".orders"
;
total += jdbcTemplate.queryForObject(sql, Integer
.class)
;
}
return
total;
}
示例程式碼:跨分片分頁查詢
public List<Order> paginateOrders(int page, int size)
{
List<Order> allOrders =
new
ArrayList<>();
for
(String table : List.of(
"orders_1"
,
"orders_2"
)) {
String sql =
"SELECT * FROM "
+ table +
" LIMIT 100"
;
allOrders.addAll(jdbcTemplate.query(sql,
new
OrderRowMapper()));
}
allOrders.sort(Comparator.comparing(Order::getCreatedAt));
return
allOrders.stream()
.skip((page -
1
) * size)
.limit(size)
.collect(Collectors.toList());
}
基於 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現的後臺管理系統 + 使用者小程式,支援 RBAC 動態許可權、多租戶、資料許可權、工作流、三方登入、支付、簡訊、商城等功能
專案地址:https://github.com/YunaiV/yudao-cloud 影片教程:https://doc.iocoder.cn/video/
3. 分散式事務問題
問題描述
解決方案
3.1 分散式事務框架
-
Seata :支援跨庫的分散式事務。 -
示例程式碼 :
@GlobalTransactional
publicvoidcreateOrder(Order order)
{
orderService.saveOrder(order);
// 寫入庫A
stockService.reduceStock(order.getProductId());
// 更新庫B
}
3.2 柔性事務
-
使用訊息中介軟體實現最終一致性。 -
典型實現:RocketMQ 訊息事務 。
4. 分片鍵設計問題
問題描述
解決方案
4.1 分片鍵設計原則
-
資料分佈均勻 :避免熱點問題。 -
常用查詢欄位 :儘量選高頻查詢欄位。
4.2 路由表
-
維護全域性路由表,對映分片鍵到分表。
示例程式碼:路由表查詢
public String getTargetTable(int userId)
{
String sql =
"SELECT table_name FROM routing_table WHERE user_id = ?"
;
return
jdbcTemplate.queryForObject(sql,
new
Object[]{userId}, String
.class)
;
}
5. 資料遷移問題
問題描述
解決方案
5.1 雙寫策略
-
資料遷移期間,舊錶和新表同時寫入。 -
待遷移完成後,切換到新表。
5.2 增量同步
-
使用 Canal 監聽 MySQL Binlog,將資料遷移到新分片。
示例:Canal 配置
canal.destinations:
example:
mysql:
hostname: localhost
port:
3306
username: root
password: password
kafka:
servers: localhost:
9092
topic: example_topic
6. 分頁查詢問題
問題描述
解決方案
-
各分片分頁後合併 :先按分片分頁查詢,業務層合併排序後分頁。 -
中介軟體支援分頁 :如 ShardingSphere。
示例程式碼:跨分片分頁
public List<Order> queryPagedOrders(int page, int size)
{
List<Order> results =
new
ArrayList<>();
for
(String table : List.of(
"orders_1"
,
"orders_2"
)) {
results.addAll(jdbcTemplate.query(
"SELECT * FROM "
+ table +
" LIMIT 100"
,
new
OrderRowMapper()));
}
results.sort(Comparator.comparing(Order::getCreatedAt));
return
results.stream().skip((page -
1
) * size).limit(size).collect(Collectors.toList());
}
7. 運維複雜性
問題描述
-
資料庫例項多,監控和備份複雜。 -
故障排查需要跨多個庫。
解決方案
-
自動化運維平臺 :如阿里雲 DMS。 -
監控工具 :使用 Prometheus + Grafana 實現分片監控。
總結
問題 | 解決方案 |
---|---|
全域性唯一 ID | 雪花演算法、號段分配、Leaf |
跨庫跨表查詢 | 中介軟體支援(如 ShardingSphere)或手動合併 |
分散式事務 | 分散式事務框架(Seata)、訊息最終一致性 |
分片鍵設計問題 | 路由表或高效分片鍵 |
資料遷移問題 | 雙寫策略或增量同步(如 Canal) |
分頁查詢問題 | 分片查詢後合併排序 |
運維複雜性 | 自動化工具(DMS)、監控工具(Prometheus + Grafana) |





