雪花ID生成器 - 创建唯一的分布式ID
这款免费雪花(Snowflake)ID生成器可根据时间戳、机器ID、数据中心ID和序列号这四部分,生成一个全局唯一的64位整数ID,并以按位分解的方式清楚展示每一部分在二进制中所占的具体位数。它同时支持解析已有的雪花ID,从中反推出生成时间等信息,适合分布式系统和微服务架构中的主键设计与调试排查。
雪花ID生成器
可选:Unix时间戳(毫秒),默认为当前时间
机器ID(0-31)
数据中心ID(0-31)
序列号(0-4095)
文档
什么是 Snowflake ID 生成器?
Snowflake ID 生成器根据时间戳、机器标识符和序列号构建一个唯一的 64 位数字。Twitter 于 2010 年创建了这种格式,使生成 ID 的各台机器无需相互协调。许多服务器可以同时生成 ID,而不必询问“这个编号用过了吗?”本工具根据输入的值构建一个 Snowflake ID,并展示这些值如何填入 64 位。
Snowflake ID 生成器的工作方式
生成器接收四个输入:
- 时间戳:以毫秒为单位的 Unix 时间戳。留空则使用当前时间。
- 机器 ID:从 0 到 31 的整数(5 位)。这是 Twitter 最初所称的“工作进程 ID”。
- 数据中心 ID:从 0 到 31 的整数(5 位)。
- 序列号:从 0 到 4095 的整数(12 位),用于区分同一毫秒内创建的 ID。
本工具将这四个值合并为一个 64 位 ID,并将结果拆分为时间戳、机器和序列三个部分显示。
时间戳从一个固定的起点开始计算,这个起点称为 Twitter 纪元:2010年11月4日,1:42:54.657 UTC,即 Unix 纪元之后 1,288,834,974,657 毫秒。本生成器不允许更改这个起点,它生成的每个 ID 都以这一固定日期为基准计算。
Snowflake ID 的结构
Snowflake ID 是一个由四部分组成的 64 位整数,从最高有效位向下读取:
| 位 | 字段 | 值域 |
|---|---|---|
| 1 | 符号位 | 始终为 0 |
| 41 | 时间戳 | 自 Twitter 纪元起经过的毫秒数 |
| 5 | 数据中心 ID | 0–31 |
| 5 | 机器(工作进程)ID | 0–31 |
| 12 | 序列号 | 0–4095 |
最高位始终为 0,因此 Snowflake ID 始终是正数。41 位的时间戳字段和 12 位的序列字段是使 Snowflake ID 便于排序的两个部分:较晚生成的 ID 具有更大的时间戳字段,因此会排在较早生成的 ID 之后。
Snowflake ID 公式
生成器使用以下公式构建 ID:
1delta = timestamp - 1288834974657
2id = (delta << 22) | (dataCenterId << 17) | (machineId << 12) | sequence
3<< 表示左移位。将一个数字左移 22 位,等同于将其乘以 2²²,即 4,194,304。移位量(22、17、12)直接取自各字段的宽度:序列字段宽 12 位,因此机器 ID 上移 12 位;机器字段宽 5 位,因此数据中心 ID 上移 17 位(12 + 5);其余字段依此类推。
如何计算 Snowflake ID:完整示例
假设有人输入:
- 时间戳:1,288,834,975,657(恰好比 Twitter 纪元晚 1,000 毫秒)
- 数据中心 ID:1
- 机器 ID:1
- 序列号:0
步骤 1——求时间差。 用时间戳减去纪元:1,288,834,975,657 − 1,288,834,974,657 = 1,000。
步骤 2——将各字段移到相应位置。
- 时间戳:1,000 << 22 = 4,194,304,000
- 数据中心 ID:1 << 17 = 131,072
- 机器 ID:1 << 12 = 4,096
- 序列号:0
步骤 3——使用按位或进行组合。 由于移位后的字段互不重叠,将它们相加与对它们执行按位或运算的结果相同:
4,194,304,000 + 131,072 + 4,096 + 0 = 4,194,439,168
这就是该输入对应的 Snowflake ID。本工具的结果视图会把同一个 64 位二进制串重新拆分为 41 位的时间戳块、10 位的机器块和 12 位的序列块,因此数字的结构一目了然。
Snowflake ID 的应用场景
Twitter 设计这种格式,是为了在众多机器上生成唯一且大致按时间排序的 ID,而无需每台服务器都去检查的中央计数器。其他平台也借鉴了这一思路。例如,Discord 表示其 ID 采用 Twitter 的 Snowflake 格式。同样的思路也出现在数据库分片、电子商务系统的订单 ID 和分布式应用的事件日志中:凡是需要许多机器各自独立分配 ID,又要让 ID 大致按时间排序的地方,都可以用到。
Snowflake ID 的局限性
生产环境中的 Snowflake 生成器通常维护自己的运行时钟:在同一毫秒内每生成一个 ID,序列号就加一;序列号达到 4,095 后,则等待下一毫秒。本工具在两次计算之间不保留任何状态。它根据输入的时间戳、各类 ID 和序列号构建一个 ID,因此适合用来研究这种格式,但与实际运行的生产服务不同。
无论由哪种服务实现,这种设计都有固定限制:
- 固定纪元:此生成器只接受 2010年11月4日(Twitter 纪元)及之后的时间戳。更早的日期无法编码。
- 时间戳上限:41 位的时间戳字段大约在 2080 年七月耗尽。此后,纪元以来的时间差无法放入 41 位中。
- 序列限制:同一台机器在同一毫秒内最多只能生成 4,096 个不同的 ID(0–4095),再继续生成就会出现重复值。
- 机器数量空间:机器 ID 和数据中心 ID 各占 5 位,因此一次部署可以分配 1,024 个不同的机器标识(32 × 32),而不会发生冲突。
- 局部排序而非全局排序:只有当 ID 来自时钟同步的机器时,它们相互之间的排序才是正确的。机器之间的时钟偏差可能破坏严格的时间顺序。
Snowflake ID 的历史
Twitter 在将存储从 MySQL 迁移到 Cassandra 的过程中构建了 Snowflake,因为 Cassandra 不提供顺序 ID 的功能。设计目标是生成不超过 64 位、唯一、大致按时间排序且可直接排序的 ID。初始版本于 2010 年发布,后来被停用,由内部重写的版本取代。其他大型平台也以修改后的形式借鉴了这一设计,因为它们有同样的需求:由许多机器同时生成唯一且可排序的 ID。
常见问题
什么是 Snowflake ID? Snowflake ID 是一个由时间戳、机器标识符和序列号组成的 64 位数字,旨在让许多机器无需相互协调即可生成唯一 ID。
Snowflake ID 的公式是什么?
id = ((timestamp − epoch) << 22) | (dataCenterId << 17) | (machineId << 12) | sequence,其中纪元是一个固定的起始日期,<< 表示左移位。
可以在此生成器中更改纪元吗? 不可以。此工具始终以固定的 Twitter 纪元 2010年11月4日 为基准计算时间戳。没有可用于设置其他起始日期的字段。
此工具能解码现有的 Snowflake ID 吗? 不能。它只会根据输入的时间戳、机器 ID、数据中心 ID 和序列号生成新的 ID,然后显示该新 ID 的位分解结果。
一台机器每毫秒可以生成多少个 Snowflake ID? 最多 4,096 个,因为序列字段宽 12 位,取值范围为 0 至 4,095。
该生成器可以生成有效时间戳直到哪一年? 大约到 2080 年七月。41 位的时间戳字段从固定的 2010 年纪元起算,最多可容纳约 69.7 年(Twitter 的说明将其取整为 69 年),此后数值会溢出该字段。
参考文献
- Twitter。Snowflake README(snowflake-2010 标签),GitHub。Snowflake README — 无需协调、大致按时间排序、不超过 64 位的 ID;41 位时间(69 年)、10 位机器 ID(1,024 台机器)、12 位序列(每台机器每毫秒 4,096 个);起因是从 MySQL 迁移到 Cassandra。
- Twitter。IdWorker.scala(snowflake-2010 标签),GitHub。Snowflake IdWorker.scala — twepoch = 1288834974657;5 位工作节点、5 位数据中心、12 位序列;移位量为 12、17 和 22。
- Discord。API Reference: Snowflakes。Discord API 参考 — Discord 的 ID 采用 Twitter 的 Snowflake 格式。
- Twitter。Snowflake README(master),GitHub。Snowflake 停用通知 — 初始版本于 2010 年发布,现已停用。