Snowflake(雪花算法)是 Twitter 开源的一种分布式 ID 生成算法。其核心是在不依赖数据库的情况下,生成全局唯一且趋势递增的 64 位整型 ID。
一、ID 结构
Snowflake 将 64 位 Long 类型划分为四个部分:
0 - 0000000000 0000000000 0000000000 0000000000 0 - 0000000000 - 000000000000
↑ └───────────── 时间戳 (41 bits) ─────────────┘ └ 机器 ID ┘ └── 序列号 ──┘
符号位 (10 bits) (12 bits)| 组成部分 | 位数 | 说明 | 理论上限 |
|---|---|---|---|
| 符号位 | 1 bit | 始终为 0,保证 ID 为正数 | - |
| 时间戳 | 41 bit | 当前时间与起始时间的差值 (毫秒) | 约 69 年 |
| 机器 ID | 10 bit | 通常由数据中心 ID (5) + 工作机器 ID (5) 组成 | 1024 个节点 |
| 序列号 | 12 bit | 同一机器、同一毫秒内的自增计数 | 4096 个/毫秒 |
理论吞吐量: 万/秒。
二、核心优势
- 高性能:本地生成,不依赖网络 IO 和数据库,性能极高。
- 趋势递增:高位为时间戳,符合 B+ 树索引的顺序插入特性。
- 部署灵活:不依赖第三方中间件(分配机器 ID 除外)。
三、常见问题与方案
时钟回拨 (Clock Drift)
- 问题:由于依赖系统时间,若机器时间回拨,可能生成重复 ID。
- 对策:检测到
currentTime < lastTime时,抛出异常或短时间阻塞等待。
机器 ID 分配
- 问题:如何在集群中为每个实例分配唯一的 10 位机器 ID?
- 对策:使用 ZooKeeper/Redis 临时顺序节点,或在容器启动时通过环境变量配置。
前端精度丢失 (JS Precision)
- 问题:JavaScript 的
Number类型最大支持 ,Snowflake (64 位) 返回前端会发生精度丢失。 - 对策:后端向前端传输时,统一转换为 String 类型。
四、方案对比
| 特性 | 数据库自增 | UUID | Snowflake |
|---|---|---|---|
| 有序性 | 严格递增 | 无序 | 趋势递增 |
| 长度 | 4/8 字节 | 16 字节 (字符串长) | 8 字节 (Long) |
| 可用性 | 强依赖 DB | 极高 | 极高 |
| 信息安全 | 易被猜出 ID 规律 | 无规律 | 包含时间戳信息 |
五、总结
Snowflake 是分布式系统中生成 ID 的首选方案。它在 唯一性、有序性、性能 之间取得了极佳的平衡。除非有特殊业务需求(如完全随机或短 ID),否则 Snowflake 几乎是工业界的标准实践。