TL;DR(30 秒扫完)
- 分片算法 6 种:Range / Mod / 一致性哈希 / 基因法 / List / Key,各对应不同扩容代价
- 扩容代价对比:Mod N→N+1 迁 80%+;一致性哈希/基因法只迁 1/N 或接近 0;翻倍扩容恒 50%
- 全局 ID 6 种:数据库自增 / UUIDv4 / UUIDv7 / 雪花 / 号段 / 基因法,按性能+有序+分布式+防猜测四维选
- 雪花 64 位:1 符号 + 41 毫秒时间戳 + 10 机器 ID + 12 序列号 = 单机每秒 4096
- 雪花的三个坑:时钟回拨 / workerId 冲突 / 单机 TPS 上限
- 基因法:ID 低 4 位嵌
hash(buyer_id) % 16,查单时截取低 4 位直接路由,电商必备
关键结论
结论 A分片算法没有最好的,只有最适合业务生命周期的组合
结论 B一致性哈希用虚拟节点(100-200 个/物理节点)解决负载不均
结论 C全局 ID 的核心权衡是 有序 vs 高性能 vs 分布式 vs 防猜测
结论 D雪花是通用默认,号段/基因法是对特定痛点的加强版
完整讲解(费曼四步)
STEP 1 · 概念
分片算法决定"分片键 → 分片号"的映射规则;全局 ID 解决"分片后主键跨片唯一有序"的问题。STEP 2 · 大白话
快递分拣类比:- Mod:按地址末位 mod N 分到 N 个快递柜(均匀但柜子数改了全都要重新分)
- 一致性哈希:环上排队,柜子加了只影响附近一段
- 基因法:包裹编号本身就写着"去几号柜",扫码直达
- 时间戳 = 年号
- 机器 ID = 工厂编号
- 序列号 = 流水线次品重制号
- 合起来 = "2026 年 3 月 22 号,北京 5 号工厂,第 7 号工人,第 400 个产品"
STEP 3 · 底层
六种分片算法
| 算法 | 分片方式 | 适用场景 | 扩容代价 | 典型代表 |
|---|---|---|---|---|
| Range | 按区间切 | 时序数据、按月归档 | 高(旧数据要迁) | 按月分表 |
| Mod | hash(key) % N | 均匀分布要求高 | 极高(几乎全表迁) | ShardingSphere 默认 |
| 一致性哈希 | 环形 + 虚拟节点 | 频繁扩容场景 | 低(1/N) | 分布式缓存路由 |
| 基因法 | ID 内嵌分片位 | 主键即路由键 | 极低(新片新数据) | 电商订单 |
| List | 枚举映射 | 少量离散值 | 中 | 多租户 SaaS |
| Key | MySQL 内置哈希 | 分区场景 | — | 分区引擎层 |
| 场景 | 迁移比例 | 说明 |
|---|---|---|
| Mod 8 → 9 | ~88.9% | hash(x) % 8 vs hash(x) % 9 几乎独立 |
| Mod 8 → 16 | ~50% | 翻倍扩容恒定 50% |
| 一致性哈希 8 → 9 | ~11.1% | 1/(N+1) |
| 基因法 | ~0% | 新数据自动落新片 |
- 分库按一致性哈希 + 分表按 Range:库层解决扩容均衡,表层解决时序归档
- 分库按 Gene + 分表按 Mod:基因法保证路由一致,库内取模保证均匀
- 两级 Hash:分库 = hash(user_id) % 8,分表 = hash(order_id) % 16 → 8 库 × 16 表 = 128 分片
一致性哈希的虚拟节点
问题:物理节点少时(如 3 个),环上映射分布不均,某节点可能承担 60% 数据。 解决:每个物理节点在环上映射 100-200 个虚拟点。物理节点 A → 虚拟点 A1, A2, ..., A100
物理节点 B → 虚拟点 B1, B2, ..., B100
物理节点 C → 虚拟点 C1, C2, ..., C100
数据落在虚拟点,虚拟点映射到物理节点。这样哈希分布均匀得多。
六种全局 ID 方案
| 方案 | 有序 | 高性能 | 分布式 | 防猜测 | 典型场景 |
|---|---|---|---|---|---|
| 数据库自增 | ✅ | ❌ | ❌ | ❌ | 单库单表 |
| UUIDv4 | ❌ | ✅ | ✅ | ✅ | 无要求场景 |
| UUIDv7 | ✅ | ✅ | ✅ | 部分 | 新型替代 |
| 雪花 | ✅ | ✅ | ✅ | ❌ | 电商/订单 |
| 号段 | ✅ | ✅ | ✅ | ❌ | 高 QPS 场景 |
| 基因法 | ✅ | ✅ | ✅ | ❌ | 分片路由 |
雪花算法的 64 位组成
┌──┬──────────────────────────┬─────────────┬──────────────────┐
│ 1 │ 41 位 │ 10 位 │ 12 位 │
│符号│ 毫秒时间戳 │ 机器 ID │ 序列号 │
│ │ (约 69 年) │ (1024 台) │ (单机 4096/秒) │
└──┴──────────────────────────┴─────────────┴──────────────────┘
Java 伪代码:
long id = timestamp << 22
| (datacenterId << 17)
| (workerId << 12)
| sequence;
雪花的三个经典坑
1. 时钟回拨:NTP 校时可能回拨几秒,导致同一毫秒生成重复 ID。 处理方案:- 拒绝生成:检测到回拨直接抛异常,等追上
- 备用时间戳:用上次成功时间戳的下一个毫秒
- 暂停等待:sleep 几毫秒直到追上(推荐)
- ZK 临时节点抢占(美团 Leaf-Snowflake)
- DB 唯一约束(INSERT 冲突重试)
- 配置文件预分配(简单但有冲突风险)
号段模式(Segment)
-- ID_SEQ 表
CREATE TABLE id_seq (
name VARCHAR(64) PRIMARY KEY,
max_id BIGINT NOT NULL,
step INT NOT NULL DEFAULT 1000
);
- 应用本地缓存 1000 个 ID,用完再去 DB 取下一段
- 1000 应用请求换 1 次 DB 请求,DB 压力极低
- 双 Buffer 预热减少重启浪费
基因法(Gene Method)
思路:ID 低 4 位嵌hash(buyer_id) % 16。
64 位雪花 ID:
[1][41 位时间戳][10 位机器 ID][12 位序列号]
基因法改造:
[1][41 位时间戳][10 位机器 ID][8 位序列号][4 位分片位]
↑
hash(buyer_id) % 16
查询时截取低 4 位 → 直接路由到对应分片,不需要额外查用户表。
代价:主键必须能改(不能用自增 ID),要占用位数。
STEP 4 · 简化
一句话总结:分片算法选扩容代价最小的组合;全局 ID 选能覆盖主查询路径的方案;两者常常配合(基因法 = 分片算法 + 全局 ID 二合一)。 记忆口诀:- 扩容频繁 → 一致性哈希 / 基因法
- 归档频繁 → Range
- 极致均匀 → Mod + 2 的幂
- 多租户 → List
- 主键即路由 → 基因法
- 雪花三坑 → 回拨 / workerId / TPS 上限
常见误区
说"一致性哈希永远比 Mod 好"
分片数固定且很少扩时,Mod 完全够用;一致性哈希需要虚拟节点调优
说"雪花保证不重复"
雪花理论上保证,但时钟回拨会导致同毫秒重复 ID
说"UUIDv4 就是 UUID"
UUIDv4 完全随机,导致 B+ 树随机插入,写入性能差 3-10 倍;UUIDv7 用时间戳前缀修复了
说"基因法就是雪花"
基因法是分片算法,雪花是ID 生成算法;基因法可以在雪花 ID 上叠加分片位
说"号段模式不浪费 ID"
应用重启会丢掉未用完的号段,不连续但保证唯一
说"雪花单机能撑很高 QPS"
12 位序列号上限是 4096 个/秒/worker
延伸追问
N=8 扩到 N=12 要迁多少数据?
hash(x) % 8 和 hash(x) % 12 的理论最小公约数是 hash(x) % 24。只有 hash(x) % 24 == 0 才不迁,约 8.3% 不迁,91.7% 要迁。hash(x) & (N-1) 什么时候等价于 hash(x) % N?仅当 N 是 2 的幂时。否则不等价(如
11 & 3 = 3,11 % 4 = 3 巧合;6 & 3 = 2,6 % 4 = 2 巧合;5 & 5 = 5,5 % 8 = 5 巧合,但换个数字就崩了)。雪花遇到时钟回拨怎么办?
三种:①拒绝生成抛异常 ②备用时间戳 ③sleep 等待追上(推荐)。严重回拨要告警人工介入。
号段模式如何减少重启浪费?
双 Buffer:本地两个 buffer,一个在用,一个预热。用完了无缝切换到预热的,同时启动预热下一个。
为什么 UUIDv4 会导致 B+ 树写入性能差 3-10 倍?
随机 ID 导致 B+ 树页随机插入,频繁 page split、页内移动大量数据、破坏页的局部性。UUIDv7 用时间戳前缀(48 位)修复了这个问题。
Leaf-Snowflake 的 workerId 分配怎么保证不冲突?
ZK 临时节点抢占:每个 worker 启动时向 ZK 的
/leaf-snowflake/workers/ 下注册一个临时节点,ZK 保证同名节点唯一。ZK 会话断开会清理临时节点。速查表
分片算法 6 种: Range / Mod / 一致性哈希 / 基因法 / List / Key
扩容代价: Mod 8→9=89% / 一致性哈希=1/N / 基因法≈0%
雪花 64 位: 1+41+10+12(符号/时间戳/机器/序列)
雪花 TPS: 单机 4096/秒
雪花三坑: 时钟回拨 / workerId 冲突 / TPS 上限
号段: 1000 应用请求换 1 次 DB 请求
基因法: 低 4 位嵌 hash(user_id) % 16
UUIDv4 坑: 随机导致 B+ 树随机插入,写入慢 3-10 倍
UUIDv7 修复: 前 48 位时间戳前缀
组合方案: 分库一致性哈希 + 分表 Range
Anki 候选卡片
Q: 分片算法六种分别是什么?
A: Range / Mod / 一致性哈希 / 基因法 / List / Key
Q: Mod N→N+1 扩容迁移多少数据?
A: 约 N/(N+1),8→9 迁 88.9%;翻倍扩容恒 50%
Q: 雪花算法 64 位组成?
A: 1 符号 + 41 毫秒时间戳 + 10 机器 ID + 12 序列号(4096/秒)
Q: 雪花算法的三个经典坑?
A: 时钟回拨 / workerId 冲突 / 单机 TPS 上限
Q: 号段模式如何降低 DB 压力?
A: 本地缓存 1000 ID,1000 应用请求换 1 次 DB 请求
Q: 基因法核心思想?
A: ID 低 4 位嵌
hash(user_id) % N,查单时截取低 4 位直接路由Q: UUIDv4 为什么写入性能差 3-10 倍?
A: 随机 ID 导致 B+ 树随机插入,频繁 page split
Q: 一致性哈希虚拟节点作用?
A: 每物理节点映射 100-200 虚拟点,解决物理节点少时负载不均
关联题目
- ⚠️ 《分表算法都有哪些?》— 2026-09-23 Round 1, ⭐⭐(只答 2 种,缺基因法/扩容代价)
- ⚠️ 《分表后全局 ID 如何生成?》— 2026-09-23 Round 1, ⭐⭐⭐(只答雪花,缺号段/基因法/时钟回拨)
关联知识
分片算法选扩容代价最小的组合;全局 ID 选能覆盖主查询的方案
快递分拣:Mod 按地址末位分柜,一致性哈希环形排队,基因法包裹编号自带柜子号
✦ 记 忆 口 诀 ✦
扩容频繁用一致性哈希或基因法 / 归档频繁用 Range / 主键即路由用基因法 / 雪花通用默认
关键可视化
六种分片算法扩容代价
flowchart TB A[分片算法] --> R[Range] A --> M[Mod] A --> C[一致性哈希] A --> G[基因法] A --> L[List] A --> K[Key] R --> RC[高 旧数据要迁] M --> MC[极高 N 到 N 加 1 迁 80 加] C --> CC[低 只迁 N 分之一] G --> GC[极低 新片新数据] L --> LC[中] K --> KC[引擎层内建]
一致性哈希环形映射
flowchart LR R[环形 2 的 32 次方空间] --> V1[虚拟点 A1 到 A100 物理节点 A] R --> V2[虚拟点 B1 到 B100 物理节点 B] R --> V3[虚拟点 C1 到 C100 物理节点 C] K[数据 key] --> H[hash key 顺时针找] H --> V1 H --> V2 H --> V3 V1 -.扩容.-> V4[加物理节点 D 只影响相邻] V2 -.扩容.-> V5[只迁 1 除以 N 加 1 数据]
雪花算法 64 位组成
flowchart LR S[64 位 ID] --> S1[1 位 符号位 固定 0] S --> S2[41 位 毫秒时间戳 约 69 年] S --> S3[10 位 机器 ID 1024 台] S --> S4[12 位 序列号 单机 4096 每秒] S3 --> P[时钟回拨] S3 --> Q[workerId 冲突] S4 --> R[单机 TPS 上限]
六种全局 ID 方案对比
flowchart TB I[全局 ID 方案] --> A[数据库自增 单库单表] I --> B[UUIDv4 随机 有序性差] I --> C[UUIDv7 时间戳前缀 修复 B 树] I --> D[雪花 单机 4096 每秒] I --> E[号段 1000 应用请求换 1 次 DB] I --> F[基因法 分片位嵌 ID 低位] D --> G[最通用 电商订单] E --> H[高 QPS 场景] F --> I2[主键即路由键]
基因法原理
flowchart LR S[64 位雪花 ID] --> P1[1 位符号] S --> P2[41 位时间戳] S --> P3[10 位机器 ID] S --> P4[8 位序列号] S --> P5[4 位分片位] P5 --> F[formula hash buyer_id mod 16] F --> Q[查询时截取低 4 位] Q --> R[直接路由到对应分片] R --> W[不需要额外查用户表]
雪花算法三个经典坑
flowchart TB S[雪花坑] --> P1[时钟回拨] P1 --> H1[拒绝生成 抛异常] P1 --> H2[备用时间戳 上次成功时间戳加 1] P1 --> H3[sleep 等待追上 推荐] S --> P2[workerId 冲突] P2 --> H4[ZK 临时节点抢占] P2 --> H5[DB 唯一约束] P2 --> H6[配置文件预分配] S --> P3[单机 TPS 上限] P3 --> H7[12 位序列号 4096 每秒] H7 --> H8[超过要拆多台 worker]
知识关系
⬆️ 前置(Prerequisite)
sharding-fundamentals🔄 延伸(Extends)
sharding-migration
🎯 概念
📏 规则
⚠️ 误区
🔍 追问
✨ 口诀
共 0 张卡,点击翻面