雪花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 年创建了这种格式,让每条推文都有一个可由多台服务器同时生成的标识符,而无需互相询问“这个数字是否已经使用过?”此工具根据输入的值生成一个 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:
其中,d 是增量,t 是以毫秒表示的输入时间戳,I 是生成的 ID,c 是数据中心 ID,m 是机器 ID,s 是序列号。
<< 表示左移位。将一个数字左移 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 位的时间戳块、宽度为5位的数据中心块、宽度为5位的机器块和 12 位的序列块,从而保留数字的结构。
Snowflake ID 的应用场景
Twitter 创建这种格式,是为了在数千台数据库机器之间为推文生成唯一且大致按时间排序的 ID,无需设置一个所有服务器都必须查询的中央计数器。Discord 和 Instagram 后来采用了类似的 64 位 ID 设计,用于消息和帖子。同样的思路还应用于数据库分片、电商系统的订单 ID,以及分布式应用中的事件日志。只要许多机器需要独立分配 ID,同时还要求 ID 大致按时间排序,这种设计就适用。
Snowflake ID 的局限性
生产环境中的 Snowflake 生成器通常会维护自己的运行时钟:对于同一毫秒内生成的每个 ID,它都会递增序列号;当序列号达到 4,095 后,则等待下一个毫秒。此工具在计算之间不会保存状态。它根据输入的值生成一个 ID,因此适合探索这种格式,但不同于实际运行的生产服务。
无论由哪种服务实现,这种设计都有固定限制:
- 固定纪元:此生成器只接受 2010年11月4日(Twitter 纪元)及之后的时间戳。更早的日期无法编码。
- 时间戳上限:41 位的时间戳字段大约在 2080 年七月耗尽。此后,纪元以来的时间差无法放入 41 位中。
- 序列限制:同一台机器在同一毫秒内最多只能生成 4,096 个不同的 ID(0–4095),再继续生成就会出现重复值。
- 机器数量空间:机器 ID 和数据中心 ID 各占 5 位,因此一次部署可以分配 1,024 个不同的机器标识(32 × 32),而不会发生冲突。
- 局部排序而非全局排序:只有当 ID 来自时钟同步的机器时,它们相互之间的排序才是正确的。机器之间的时钟偏差可能破坏严格的时间顺序。
Snowflake ID 的历史
Twitter 于 2010 年宣布了 Snowflake ID 格式,用来替代简单的数据库自增 ID,因为后者无法扩展到许多相互独立的数据库服务器。这个名称源于这样的想法:生成的 ID 就像现实中的雪花一样,不会有两个完全相同。后来,该设计以开源形式发布,并被其他需要相同功能的大型平台修改和复制:由许多机器同时生成唯一且可排序的 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 年的时间,之后该值会溢出字段。
参考文献
- “宣布 Snowflake。”Twitter 工程博客,2010 年。
- "Snowflake ID." Wikipedia,https://en.wikipedia.org/wiki/Snowflake_ID