MySQL 分片系统设计
-
分片架构完整流程
-
SQL 路由原理
-
ShardingSphere 内部工作机制
-
分片键设计方法
-
分片生产故障案例
-
云数据库平台如何治理分片
1. 一个真实的 MySQL 分片架构
先看大型系统通常是什么样子。
用户请求
|
|
业务服务
|
|
-------------------
| |
SQL访问层 数据访问层
|
|
ShardingSphere
|
|
------------------------------------------------
| | |
订单分片库0 订单分片库1 订单分片库2
| | |
mysql-master0 mysql-master1 mysql-master2
|
slave slave slave
这里有几个关键角色:
2. 业务服务
例如:
订单服务:
createOrder()
queryOrder()
它只知道:
select * from orders
不知道数据在哪。
3. ShardingSphere
它负责:
-
SQL解析
-
判断目标库
-
SQL改写
-
SQL执行
-
结果合并
它实际上充当:
数据库访问代理层
4. SQL路由到底怎么实现?
这是分片最核心的地方。
假设:
有4个数据库:
order_db_0
order_db_1
order_db_2
order_db_3
规则:
database = user_id % 4
现在执行:
SELECT *
FROM orders
WHERE user_id=10001;
5. SQL解析
ShardingSphere解析SQL:
得到:
表:
orders
条件:
user_id = 10001
它知道:
user_id
是分片字段
6. 计算路由
执行:
10001 % 4
结果:
1
所以:
目标库:
order_db_1
7. SQL改写
原SQL:
SELECT *
FROM orders
WHERE user_id=10001
变成:
SELECT *
FROM order_db_1.orders
WHERE user_id=10001
8. 发送请求
连接:
mysql-01:3306
执行:
execute(sql)
9. 如果SQL没有分片键怎么办?
这是生产里面非常常见的问题。
例如:
SELECT *
FROM orders
WHERE create_time>'2026-01-01';
问题:
没有:
user_id
系统不知道:
数据在哪个库
怎么办?
10. 方案1:广播查询
发送:
db0
select...
db1
select...
db2
select...
db3
select...
然后:
合并结果。
流程:
SQL
|
分片路由判断
|
---------------------
| | |
db0 db1 db2
| | |
结果0 结果1 结果2
|
merge
|
返回用户
问题:
如果:
100个分片
一次查询:
100次SQL。
所以生产环境会限制这种查询。
11. 分片键设计为什么非常重要?
很多系统失败,不是因为技术不好,而是:
分片键选错。
假设订单表:
order_id
user_id
merchant_id
create_time
选择:
12. 方案A:
order_id
问题:
用户查询:
select *
from orders
where user_id=10001
无法定位。
只能:
扫描所有分片。
13. 方案B:
user_id
更合理。
因为:
用户订单天然聚集:
用户A
订单
支付
物流
评价
都可以定位。
但是也有问题:
超级用户:
例如:
user_id=888888
一天:
100万订单
那么:
固定分片:
db2
压力巨大。
这叫:
数据倾斜
14. 分片算法的发展
15. Hash分片
最简单:
user_id % N
优点:
简单。
缺点:
扩容困难。
例如:
4个库:
id %4
扩展:
8个库:
id %8
大量数据迁移。
16. 一致性哈希
思想:
把节点放到环上。
例如:
DB0
/ \
DB3 DB1
DB2
数据:
根据hash定位。
增加节点:
只影响附近数据。
例如:
增加:
DB4
只迁移:
DB3附近的数据
17. 虚拟分片
现在大型系统更常用。
例如:
不是:
4个数据库
而是:
1024个逻辑分片
例如:
user_id
|
hash
|
slot 0-1023
|
映射
|
真实数据库
结构:
slot
0-255
|
db0
256-511
|
db1
512-767
|
db2
768-1023
|
db3
扩容:
增加:
db4
只迁移部分slot。
这也是很多分布式系统思想。
例如:
-
Redis Cluster
-
Elasticsearch shard
-
Kafka partition
都有类似思想。
18. 分片和事务问题
这是很多面试不会讲,但生产很重要。
单库:
事务:
BEGIN;
insert order;
insert payment;
COMMIT;
一个MySQL完成。
分片后:
订单:
order_db_1
支付:
payment_db_2
怎么办?
变成:
事务跨两个数据库
叫:
分布式事务
传统方案:
19. XA事务
流程:
协调者
|
|
----------------
DB1 prepare
DB2 prepare
|
commit
问题:
性能差。
互联网常用:
20. 最终一致性
例如:
订单:
创建订单
先写:
order_db
发送消息:
Kafka
消费者:
payment服务
更新支付。
架构:
订单服务
|
|
订单库
|
消息队列
|
支付服务
|
支付库
21. 生产故障案例
22. 案例1:热点分片
背景:
电商活动。
分片:
user_id % 16
正常:
每个库:
CPU 40%
活动开始:
明星用户:
user_id=8888
产生:
50万订单
结果:
db8:
CPU 100%
IO 100%
其他:
30%
现象:
订单接口延迟增加
排查:
看:
QPS
慢SQL
CPU
磁盘IO
锁等待
发现:
单分片压力异常
解决:
短期:
限流。
长期:
改变分片策略。
例如:
从:
user_id
变成:
user_id + order_id
或者:
增加:
二级分片
23. 云数据库平台如何管理分片?
这个和你的工作方向更相关。
云平台不会人工看每个库。
一般有:
24. 资源监控
采集:
MySQL Exporter:
CPU
QPS
TPS
Buffer Pool
Slow Query
Lock Wait
Replication Delay
进入:
Prometheus
25. 自动诊断
例如规则:
if
CPU > 90%
and
持续10分钟
and
QPS增长
then
判断热点分片
26. 自动治理
可能动作:
26.1. 禁止新实例调度
类似你之前设计的:
数据库节点资源池。
例如:
node mysql-01
CPU 95%
禁止创建实例
26.2. 分片迁移
例如:
db2压力高
迁移slot 600-700
到db5
26.3. 自动扩容
例如:
order_db数量:
4
|
8
27. 对你的学习路线建议
结合你现在:
-
Kubernetes
-
Prometheus
-
Python自动化
-
云数据库运维
-
AIOps方向
MySQL分片建议学习顺序:
第一阶段
MySQL主从复制
↓
Binlog
↓
读写分离
第二阶段
分库分表
↓
ShardingSphere
↓
分片算法
第三阶段
分布式事务
↓
消息最终一致性
↓
CAP理论
第四阶段
数据库智能运维
指标采集
↓
异常检测
↓
容量预测
↓
自动调度
你之前做的“根据 MySQL 节点指标决定是否允许创建实例”的思路,本质上已经接近云数据库资源调度系统,下一步可以继续深入:
“云数据库平台如何实现 MySQL 实例自动调度、容量预测和故障自愈(类似腾讯云数据库内部架构)”。 这个方向和 AIOps 结合会更贴近你的目标。
关联文档
- MySQL 基础:MySQL 数据库基础与运维入口。
