MySQL

MySQL 分片算法

·11 分钟阅读·4377 字

整理 MySQL 分片算法 的核心概念、关键流程与实践要点

📋 目录

MySQL 分片算法

在理解各种分片算法之前,需要先明确一个核心问题:

分片算法解决的不是“如何存储数据”,而是“给定一条数据,如何决定它应该进入哪个分片”。

例如:

现在有:

用户表 user

user_id | name
----------------
10001   | Tom
10002   | Jack
10003   | Alice

有三个数据库:

db0
db1
db2

系统必须回答:

user_id=10001

应该放:

db0?
db1?
db2?

这个映射关系:

分片键
   |
   |
分片算法
   |
   |
目标分片

就是 Sharding Algorithm。


1. 分片算法需要解决什么问题?

一个好的分片算法通常需要考虑几个目标:

2. 数据均匀分布

希望:

db0:

1亿数据


db1:

1亿数据


db2:

1亿数据

而不是:

db0:

2.9亿


db1:

500万


db2:

500万

否则:

一个节点成为热点。


3. 查询能够快速定位

例如:

查询:

select *
from orders
where user_id=10001;

最好:

一次定位:

db1

而不是:

db0查询
db1查询
db2查询
...

4. 扩容成本低

业务增长:

原来:

4个数据库

变成:

8个数据库

希望:

不要迁移大量数据。


所以不同算法,本质是在这些目标之间做权衡。


5. Hash 分片算法

Hash 是最经典的分片算法。

6. 基本思想

使用哈希函数:

分片位置 = hash(分片键) % 分片数量

例如:

4个数据库:

db0
db1
db2
db3

用户:

user_id=10001

计算:

hash(10001)=xxx

假设:

xxx % 4 = 1

那么:

db1

7. 简单取模算法

最简单:

database = user_id % N

例如:

N=4:

10001 % 4

=1

所以:

db1

数据:

user_id=10001

↓

db1

8. 优点

8.1. 数据均衡

因为 hash 会打散数据。

例如:

用户:

1
2
3
4
5
6

经过:

id % 4

得到:

db1
db2
db3
db0
db1
db2

比较平均。


8.2. 查询效率高

因为:

已知:

user_id

直接计算:

目标数据库

不需要扫描。


9. 最大问题:扩容困难

假设:

原来:

4个库:

id % 4

数据:

10001 %4=1

在:

db1

现在扩容:

8个库:

id %8

计算:

10001%8=1

这个刚好没变化。

但是:

例如:

10002

旧:

10002%4=2


新:

10002%8=2

部分相同。

再看:

10003

旧:

3


新:

3

看起来没问题。

但是:

实际上:

当 N 从:

4→8

变化时,大量数据映射会变化。

例如:

旧:

id%4

范围:

0 1 2 3

新:

0 1 2 3 4 5 6 7

大量数据需要重新计算。


如果:

4个节点

100TB数据

扩容:

8节点

可能:

迁移几十TB。

生产无法接受。


10. 一致性哈希(Consistent Hash)

一致性哈希就是为了解决:

普通Hash扩容导致大量数据迁移。


11. 基本思想

普通Hash:

hash(key)%N

依赖:

N

节点数量变化:

映射全部变化。

一致性哈希:

把整个Hash空间变成一个环。

例如:

             0


       DB0       DB1



DB3                 DB2


            2^32

节点:

放在环上。


数据:

也计算hash:

例如:

user_id=10001

hash=500

然后:

顺时针找到第一个数据库。

例如:

hash位置500

↓

DB2

数据放:

DB2

12. 增加节点时发生什么?

原来:

DB0

DB1

DB2

DB3

增加:

DB4

只影响:

DB4附近的数据。

例如:

原来:

DB2负责:

500-800

现在:

DB4加入

600-700

只迁移:

600-700

这一部分。

不是全部数据。


13. 虚拟节点问题

简单一致性哈希有问题:

节点分布可能不均。

例如:

DB0


              DB1



DB2

可能:

DB0负责:

80%数据。

解决:

虚拟节点。

例如:

真实节点:

DB0

变成:

DB0-1
DB0-2
DB0-3
...

多个虚拟位置。

最终:

Hash环:

DB0-1

DB1-5

DB2-8

DB0-9

...

数据更加均匀。


14. 一致性哈希应用

典型:

15. Redis Cluster

不过 Redis 使用的是:

Slot思想。

16. CDN缓存

例如:

用户请求:

图片

根据hash:

选择缓存节点。

17. 分布式缓存


18. 范围分片(Range Sharding)

范围分片不是计算,而是按照范围划分。

例如:

订单ID:

0-1000万

放:

db0
1000万-2000万

放:

db1

结构:

db0

id:

0-10000000


db1

id:

10000001-20000000


db2

id:

20000001-30000000

19. 优点

20. 范围查询非常快

例如:

查询:

where id between 100 and 200

直接:

db0

不用广播。


21. 数据天然有序

适合:

时间数据。

例如:

日志:

2026-01

db0


2026-02

db1


2026-03

db2

22. 缺点

23. 热点问题

例如:

订单ID:

递增。

最新订单:

全部进入:

db2

结果:

db2:

CPU 100%

db0:

20%

这叫:

写热点


24. 时间分片(Time Based Sharding)

范围分片的一种特殊形式。

例如:

日志系统:

2026-01

db_01


2026-02

db_02


2026-03

db_03

非常适合:

  • 日志

  • 监控数据

  • 时序数据

例如:

Prometheus TSDB:

也是类似思想。


缺点:

冷热不均。

最近月份:

大量写入。

历史月份:

几乎不访问。


25. 目录分片(Directory Based Sharding)

也叫:

查找表分片。

核心思想:

不用算法计算。

维护一个映射表。

例如:

user_mapping


user_id | shard

10001   | db1

10002   | db3

10003   | db2

查询:

先查:

mapping表

得到:

db1

然后访问。


26. 优点

非常灵活。

可以:

人工调整。

例如:

发现:

大客户:

user_id=88888

迁移:

db5

修改:

mapping

即可。


27. 缺点

增加依赖。

如果:

mapping服务挂了:

所有查询失败。

所以通常:

缓存:

Redis

+
本地缓存

28. 组合分片算法(Composite Sharding)

生产中最常见。

因为单一算法经常不够。

例如:

电商订单。

需求:

用户查询快。

同时避免热点。

可以:

第一层:

hash user_id

第二层:

hash order_id

例如:

user_id

   |

hash

   |

16个数据库


   |

order_id hash

   |

64张表

最终:

16库 × 64表

=
1024分片

29. 雪花ID + Hash 分片

现在很多互联网系统使用。

例如:

订单ID:

Snowflake:

184729384729384

然后:

hash(order_id)%16

得到:

db7

优点:

ID趋势递增。

分片均衡。


30. 各种算法对比

算法核心思想优点缺点适合
Hash取模hash(key)%N简单均衡扩容困难固定规模系统
一致性哈希Hash环扩容影响小实现复杂缓存、节点动态变化
Range范围划分范围查询快热点明显日志、时间数据
Time按时间冷热分离最新热点时序数据
Directory映射表灵活依赖中心服务复杂业务
Composite组合能力强复杂大型互联网

31. ShardingSphere里面如何实现这些算法?

ShardingSphere把算法抽象成:

Sharding Algorithm

主要类型:

32. Standard

精确:

=

范围:

between

例如:

user_id=100

33. Complex

同时使用多个字段。

例如:

user_id

+
order_id

34. Hint

不根据SQL字段。

由业务指定。

例如:

强制访问db3

35. None

不分片。


36. 结合云数据库运维理解

对于云数据库平台,真正重要的是:

不是选择哪个算法,而是:

如何根据业务负载动态选择和调整算法。

例如:

监控发现:

shard_01

CPU:
95%

QPS:
10万


shard_02

CPU:
30%

QPS:
2万

系统应该判断:

原因:

可能:

分片键选择不合理

或者

数据倾斜

然后:

自动执行:

热点检测

↓

重新分片

↓

数据迁移

↓

更新路由规则

这就是未来 AIOps 数据库治理方向。

如果继续深入,下一步建议学习 “ShardingSphere 分片源码设计:分片规则、路由引擎、SQL改写和执行引擎源码流程”,因为它和 Kubernetes Scheduler 的调度思想非常接近。


关联文档

Yanche Blog

记录云原生、Linux、数据库等技术领域的学习心得,以及日常生活的思考与感悟。

© 2026 Yanche Blog. All rights reserved.

Powered by Astro