🛠️

Whiz Tools

Build • Create • Innovate

Twitter 雪花 ID 生成器与解析工具,支持分布式系统

生成和分析 Twitter 雪花 ID,这是一种用于分布式系统的独特 64 位标识符。该工具允许您创建新的雪花 ID 并解析现有的 ID,提供有关其时间戳、机器 ID 和序列号组件的洞察。

雪花 ID 生成器

雪花 ID 生成器

Optional: Unix timestamp in milliseconds (defaults to current time)
📚

文档

雪花 ID 生成器

介绍

雪花 ID 是一种在分布式系统中使用的唯一标识符,最初由 Twitter 开发。该工具允许您生成和分析雪花 ID,这些 ID 是由时间戳、机器 ID 和序列号组成的 64 位整数。

雪花 ID 的工作原理

雪花 ID 是由 64 位整数构成,结构如下:

  • 41 位:时间戳(自定义纪元以来的毫秒数)
  • 10 位:机器 ID(5 位用于数据中心 ID,5 位用于工作者 ID)
  • 12 位:序列号

这种结构允许每台机器每毫秒生成大约 4096 个唯一 ID。

使用雪花 ID 生成器

  1. (可选)设置自定义纪元(默认是 Twitter 的纪元:2010-11-04T01:42:54.657Z)
  2. 输入机器 ID(0-31)和数据中心 ID(0-31)
  3. 点击“生成”以创建新的雪花 ID
  4. 生成的 ID 及其组成部分将被显示

要解析现有的雪花 ID,请在“解析 ID”字段中输入它并点击“解析”。

公式

雪花 ID 是使用位运算构造的:

1ID = (timestamp << 22) | (datacenterId << 17) | (workerId << 12) | sequence
2

其中:

  • timestamp 是自纪元以来的毫秒数
  • datacenterId 是一个 5 位整数(0-31)
  • workerId 是一个 5 位整数(0-31)
  • sequence 是一个 12 位整数(0-4095)

计算

雪花 ID 生成器执行以下步骤:

  1. 获取当前时间戳(毫秒)
  2. 确保时间戳大于上次使用的时间戳(以确保唯一性)
  3. 如果时间戳与上次相同,则递增序列号
  4. 如果序列号溢出(达到 4096),则等待下一个毫秒
  5. 使用位运算组合组件以创建最终 ID

用例

雪花 ID 在以下场景中特别有用:

  1. 分布式系统:在多台机器上生成唯一 ID,而无需协调
  2. 高容量数据:为大型数据集创建可排序的 ID
  3. 微服务:确保不同服务之间的唯一标识符
  4. 数据库分片:使用时间戳或机器 ID 组件进行高效分片

替代方案

虽然雪花 ID 功能强大,但其他 ID 生成系统包括:

  1. UUID(通用唯一标识符):在需要分布式生成而不需要可排序性时非常有用
  2. 自增数据库 ID:简单但仅限于单个数据库实例
  3. ULID(通用唯一按字典排序的标识符):与雪花 ID 类似,但结构不同

边缘案例和限制

  1. 时钟同步:雪花 ID 依赖于系统时间。如果由于 NTP 调整或夏令时变化导致时钟向后移动,则可能会导致 ID 生成问题。

  2. 2038 年问题:41 位时间戳将在 2079 年溢出(假设使用 Twitter 纪元)。使用雪花 ID 的系统应为此做好计划。

  3. 机器 ID 冲突:在大型分布式系统中,确保唯一的机器 ID 可能具有挑战性,可能需要额外的协调。

  4. 序列溢出:在极高吞吐量的场景中,可能会耗尽每毫秒的 4096 个序列,可能导致延迟。

  5. 跨机器的非单调性:虽然在单台机器上 ID 是单调递增的,但在多台机器上可能不严格单调。

历史

雪花 ID 于 2010 年由 Twitter 引入,以解决分布式、时间可排序的唯一标识符的需求。此后,许多其他公司和项目也采用并调整了它们。

示例

以下是各种语言中雪花 ID 生成器的实现:

1class SnowflakeGenerator {
2  constructor(epoch = 1288834974657, datacenterIdBits = 5, workerIdBits = 5, sequenceBits = 12) {
3    this.epoch = BigInt(epoch);
4    this.datacenterIdBits = datacenterIdBits;
5    this.workerIdBits = workerIdBits;
6    this.sequenceBits = sequenceBits;
7    this.maxDatacenterId = -1n ^ (-1n << BigInt(datacenterIdBits));
8    this.maxWorkerId = -1n ^ (-1n << BigInt(workerIdBits));
9    this.sequenceMask = -1n ^ (-1n << BigInt(sequenceBits));
10    this.workerIdShift = BigInt(sequenceBits);
11    this.datacenterIdShift = BigInt(sequenceBits + workerIdBits);
12    this.timestampLeftShift = BigInt(sequenceBits + workerIdBits + datacenterIdBits);
13    this.sequence = 0n;
14    this.lastTimestamp = -1n;
15  }
16
17  nextId(datacenterId, workerId) {
18    let timestamp = this.currentTimestamp();
19
20    if (timestamp < this.lastTimestamp) {
21      throw new Error('时钟向后移动。拒绝生成 ID');
22    }
23
24    if (timestamp === this.lastTimestamp) {
25      this.sequence = (this.sequence + 1n) & this.sequenceMask;
26      if (this.sequence === 0n) {
27        timestamp = this.tilNextMillis(this.lastTimestamp);
28      }
29    } else {
30      this.sequence = 0n;
31    }
32
33    this.lastTimestamp = timestamp;
34
35    return ((timestamp - this.epoch) << this.timestampLeftShift) |
36           (BigInt(datacenterId) << this.datacenterIdShift) |
37           (BigInt(workerId) << this.workerIdShift) |
38           this.sequence;
39  }
40
41  tilNextMillis(lastTimestamp) {
42    let timestamp = this.currentTimestamp();
43    while (timestamp <= lastTimestamp) {
44      timestamp = this.currentTimestamp();
45    }
46    return timestamp;
47  }
48
49  currentTimestamp() {
50    return BigInt(Date.now());
51  }
52}
53
54// 使用
55const generator = new SnowflakeGenerator();
56const id = generator.nextId(1, 1);
57console.log(`生成的雪花 ID: ${id}`);
58

图示

以下是雪花 ID 结构的可视化表示:

时间戳(41 位) 机器 ID(10 位) 序列(12 位)

64 位雪花 ID 结构

参考文献

  1. "宣布雪花。" Twitter 工程博客,https://blog.twitter.com/engineering/en_us/a/2010/announcing-snowflake
  2. "雪花 ID。" 维基百科,https://en.wikipedia.org/wiki/Snowflake_ID
  3. "微服务中的分布式 ID 生成。" Medium,https://medium.com/swlh/distributed-id-generation-in-microservices-b6ce9a8dd93f