生成和分析Twitter雪花ID工具以获取洞察
生成和分析Twitter雪花ID,这是在分布式系统中使用的独特64位标识符。该工具允许您创建新的雪花ID并解析现有的ID,提供有关其时间戳、机器ID和序列号组件的洞察。
雪花 ID 生成器
雪花 ID 生成器
文档
雪花 ID 生成器:创建唯一的分布式系统标识符
什么是雪花 ID 生成器?
雪花 ID 生成器为分布式系统创建唯一标识符,最初由 Twitter 开发,用于处理大规模数据处理。这个强大的 唯一 ID 生成器 生成由时间戳、机器 ID 和序列号组成的 64 位整数,确保 在分布式系统中唯一性,而无需服务器之间的协调。
我们的免费在线雪花 ID 生成器工具允许您 即时生成和解析雪花 ID,非常适合与微服务、分布式数据库和高吞吐量应用程序一起工作的开发人员。
雪花 ID 生成的工作原理
雪花 ID 是具有精心设计结构的 64 位整数,确保唯一性:
- 41 位:时间戳(自自定义纪元以来的毫秒数)
- 10 位:机器 ID(5 位用于数据中心 ID,5 位用于工作者 ID)
- 12 位:序列号
这种 分布式 ID 结构 使每台机器每毫秒大约可以生成 4,096 个唯一 ID,非常适合高吞吐量的分布式系统。
如何使用我们的雪花 ID 生成器工具
按照以下简单步骤 生成唯一的雪花 ID:
- 设置自定义纪元(可选):使用默认的 Twitter 纪元(2010-11-04T01:42:54.657Z)或设置您自己的
- 配置机器 ID:输入机器 ID(0-31)和数据中心 ID(0-31)
- 生成 ID:点击“生成”以创建一个新的唯一雪花 ID
- 查看结果:查看生成的 ID 及其组件细分
解析现有的雪花 ID
要 解码雪花 ID,请在“解析 ID”字段中输入它,然后点击“解析”以查看其时间戳、机器 ID 和序列组件。
雪花 ID 生成公式
雪花 ID 算法使用位运算构造唯一标识符:
1ID = (timestamp << 22) | (datacenterId << 17) | (workerId << 12) | sequence
2
公式组件:
timestamp
:自纪元以来的毫秒数datacenterId
:标识数据中心的 5 位整数(0-31)workerId
:标识工作机器的 5 位整数(0-31)sequence
:用于每毫秒多个 ID 的 12 位整数(0-4095)
雪花 ID 计算过程
雪花 ID 生成算法遵循以下精确步骤:
- 获取当前时间戳:以毫秒为单位检索当前时间
- 确保时间顺序:验证时间戳是否超过上次使用的时间戳
- 处理相同时间戳:如果时间戳与之前相同,则递增序列号
- 防止溢出:如果序列达到 4096,则等待下一个毫秒
- 组合组件:使用位运算创建最终的唯一 ID
此过程确保 每台机器内的 ID 单调递增,同时在分布式系统中保持全局唯一性。
雪花 ID 用例和应用
雪花 ID 在各种分布式计算场景中表现出色:
主要用例
- 分布式系统:在多个机器上生成唯一 ID,无需协调
- 高容量数据处理:为大规模数据集创建可排序的 ID
- 微服务架构:确保不同服务之间的唯一标识符
- 数据库分片:使用时间戳或机器 ID 组件进行高效数据分区
现实世界应用
- 社交媒体平台:Twitter、Instagram 用于帖子和用户 ID
- 电子商务系统:订单跟踪和库存管理
- 物联网数据收集:设备事件记录和传感器数据
- 金融系统:交易处理和审计跟踪
雪花 ID 替代方案和比较
虽然 雪花 ID 功能强大,但其他 唯一 ID 生成 系统包括:
替代 ID 系统
- UUID(通用唯一标识符):适合分布式生成,无需排序要求
- 自增数据库 ID:简单解决方案,限于单个数据库实例
- ULID(通用唯一字典序可排序标识符):类似于雪花,使用 base32 编码
- NanoID:紧凑的、适用于 URL 的唯一字符串生成器,适用于 Web 应用程序
雪花 ID 限制和注意事项
了解 雪花 ID 的限制 有助于正确实施:
常见挑战
- 时钟同步问题:系统时间依赖可能导致 NTP 调整或夏令时变化的问题
- 2079 年限制:41 位时间戳溢出需要对高规模系统进行长期规划
- 机器 ID 管理:确保在大型分布式系统中唯一的机器 ID 需要协调
- 序列溢出:极高吞吐量的场景可能会耗尽每毫秒的 4096 个序列
- 跨机器排序:ID 在每台机器内是单调的,但在所有机器之间不是全局单调的
雪花 ID 的历史
雪花 ID 于 2010 年由 Twitter 引入,以解决在大规模生成分布式、时间可排序的唯一标识符的挑战。随着 Twitter 用户基础和推文数量的激增,传统的自增 ID 对其分布式架构变得不足。
该系统随后被包括 Instagram、Discord 在内的主要科技公司采用,以及无数其他需要 可扩展 ID 生成 的平台。
雪花 ID 生成器代码示例
在您喜欢的编程语言中实现 雪花 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
1import time
2import threading
3
4class SnowflakeGenerator:
5 def __init__(self, datacenter_id, worker_id, sequence=0):
6 self.datacenter_id = datacenter_id
7 self.worker_id = worker_id
8 self.sequence = sequence
9
10 self.last_timestamp = -1
11 self.epoch = 1288834974657
12
13 self.datacenter_id_bits = 5
14 self.worker_id_bits = 5
15 self.sequence_bits = 12
16
17 self.max_datacenter_id = -1 ^ (-1 << self.datacenter_id_bits)
18 self.max_worker_id = -1 ^ (-1 << self.worker_id_bits)
19
20 self.worker_id_shift = self.sequence_bits
21 self.datacenter_id_shift = self.sequence_bits + self.worker_id_bits
22 self.timestamp_left_shift = self.sequence_bits + self.worker_id_bits + self.datacenter_id_bits
23 self.sequence_mask = -1 ^ (-1 << self.sequence_bits)
24
25 self._lock = threading.Lock()
26
27 def _til_next_millis(self, last_timestamp):
28 timestamp = self._get_timestamp()
29 while timestamp <= last_timestamp:
30 timestamp = self._get_timestamp()
31 return timestamp
32
33 def _get_timestamp(self):
34 return int(time.time() * 1000)
35
36 def next_id(self):
37 with self._lock:
38 timestamp = self._get_timestamp()
39
40 if timestamp < self.last_timestamp:
41 raise ValueError("时钟向后移动。拒绝生成 ID")
42
43 if timestamp == self.last_timestamp:
44 self.sequence = (self.sequence + 1) & self.sequence_mask
45 if self.sequence == 0:
46 timestamp = self._til_next_millis(self.last_timestamp)
47 else:
48 self.sequence = 0
49
50 self.last_timestamp = timestamp
51
52 return ((timestamp - self.epoch) << self.timestamp_left_shift) | \
53 (self.datacenter_id << self.datacenter_id_shift) | \
54 (self.worker_id << self.worker_id_shift) | \
55 self.sequence
56
57## 使用示例
58generator = SnowflakeGenerator(datacenter_id=1, worker_id=1)
59snowflake_id = generator.next_id()
60print(f"生成的雪花 ID: {snowflake_id}")
61
1import java.util.concurrent.locks.Lock;
2import java.util.concurrent.locks.ReentrantLock;
3
4public class SnowflakeGenerator {
5 private final long epoch;
6 private final long datacenterIdBits;
7 private final long workerIdBits;
8 private final long sequenceBits;
9 private final long maxDatacenterId;
10 private final long maxWorkerId;
11 private final long workerIdShift;
12 private final long datacenterIdShift;
13 private final long timestampLeftShift;
14 private final long sequenceMask;
15
16 private long datacenterId;
17 private long workerId;
18 private long sequence = 0L;
19 private long lastTimestamp = -1L;
20
21 private final Lock lock = new ReentrantLock();
22
23 public SnowflakeGenerator(long datacenterId, long workerId) {
24 this.epoch = 1288834974657L;
25 this.datacenterIdBits = 5L;
26 this.workerIdBits = 5L;
27 this.sequenceBits = 12L;
28
29 this.maxDatacenterId = ~(-1L << datacenterIdBits);
30 this.maxWorkerId = ~(-1L << workerIdBits);
31
32 this.workerIdShift = sequenceBits;
33 this.datacenterIdShift = sequenceBits + workerIdBits;
34 this.timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
35 this.sequenceMask = ~(-1L << sequenceBits);
36
37 if (datacenterId > maxDatacenterId || datacenterId < 0) {
38 throw new IllegalArgumentException("datacenterId 不能大于 maxDatacenterId 或小于 0");
39 }
40 if (workerId > maxWorkerId || workerId < 0) {
41 throw new IllegalArgumentException("workerId 不能大于 maxWorkerId 或小于 0");
42 }
43 this.datacenterId = datacenterId;
44 this.workerId = workerId;
45 }
46
47 public long nextId() {
48 lock.lock();
49 try {
50 long timestamp = timeGen();
51 if (timestamp < lastTimestamp) {
52 throw new RuntimeException("时钟向后移动。拒绝生成 ID");
53 }
54
55 if (lastTimestamp == timestamp) {
56 sequence = (sequence + 1) & sequenceMask;
57 if (sequence == 0) {
58 timestamp = tilNextMillis(lastTimestamp);
59 }
60 } else {
61 sequence = 0L;
62 }
63
64 lastTimestamp = timestamp;
65
66 return ((timestamp - epoch) << timestampLeftShift) |
67 (datacenterId << datacenterIdShift) |
68 (workerId << workerIdShift) |
69 sequence;
70 } finally {
71 lock.unlock();
72 }
73 }
74
75 private long tilNextMillis(long lastTimestamp) {
76 long timestamp = timeGen();
77 while (timestamp <= lastTimestamp) {
78 timestamp = timeGen();
79 }
80 return timestamp;
81 }
82
83 private long timeGen() {
84 return System.currentTimeMillis();
85 }
86
87 public static void main(String[] args) {
88 SnowflakeGenerator generator = new SnowflakeGenerator(1, 1);
89 long id = generator.nextId();
90 System.out.println("生成的雪花 ID: " + id);
91 }
92}
93
1require 'time'
2
3class SnowflakeGenerator
4 def initialize(datacenter_id, worker_id, sequence = 0)
5 @datacenter_id = datacenter_id
6 @worker_id = worker_id
7 @sequence = sequence
8 @last_timestamp = -1
9 @epoch = 1288834974657
10
11 @datacenter_id_bits = 5
12 @worker_id_bits = 5
13 @sequence_bits = 12
14
15 @max_datacenter_id = -1 ^ (-1 << @datacenter_id_bits)
16 @max_worker_id = -1 ^ (-1 << @worker_id_bits)
17
18 @worker_id_shift = @sequence_bits
19 @datacenter_id_shift = @sequence_bits + @worker_id_bits
20 @timestamp_left_shift = @sequence_bits + @worker_id_bits + @datacenter_id_bits
21 @sequence_mask = -1 ^ (-1 << @sequence_bits)
22 end
23
24 def next_id
25 timestamp = (Time.now.to_f * 1000).to_i
26
27 raise '时钟向后移动' if timestamp < @last_timestamp
28
29 if timestamp == @last_timestamp
30 @sequence = (@sequence + 1) & @sequence_mask
31 timestamp = til_next_millis(@last_timestamp) if @sequence == 0
32 else
33 @sequence = 0
34 end
35
36 @last_timestamp = timestamp
37
38 ((timestamp - @epoch) << @timestamp_left_shift) |
39 (@datacenter_id << @datacenter_id_shift) |
40 (@worker_id << @worker_id_shift) |
41 @sequence
42 end
43
44 private
45
46 def til_next_millis(last_timestamp)
47 timestamp = (Time.now.to_f * 1000).to_i
48 timestamp = (Time.now.to_f * 1000).to_i while timestamp <= last_timestamp
49 timestamp
50 end
51end
52
53## 使用示例
54generator = SnowflakeGenerator.new(1, 1)
55snowflake_id = generator.next_id
56puts "生成的雪花 ID: #{snowflake_id}"
57
<?php class SnowflakeGenerator { private $epoch; private $datacenterIdBits; private $workerIdBits; private $sequenceBits; private $maxDatacenterId; private $maxWorkerId; private $workerIdShift; private $datacenterIdShift; private $timestampLeftShift; private $sequenceMask; private $datacenterId; private $workerId; private $sequence = 0; private $lastTimestamp = -1; public function __construct($datacenterId, $workerId) { $this->epoch = 1288834974657; $this->datacenterIdBits = 5; $this->workerIdBits = 5; $this->sequenceBits = 12; $this->maxDatacenterId = -1 ^ (-1 << $this->datacenterIdBits); $this->maxWorkerId = -1 ^ (-1 << $this->workerIdBits); $this->workerIdShift = $this->sequenceBits; $this->datacenterIdShift = $this->sequenceBits + $this->workerIdBits; $this->timestampLeftShift = $this->sequenceBits + $this->workerIdBits + $this->datacenterIdBits; $this->sequenceMask = -1 ^ (-1 << $this->sequenceBits); if ($datacenterId > $this->maxDatacenterId || $datacenterId < 0) { throw new Exception("datacenterId 不能大于 maxDatacenterId 或小于 0"); } if ($workerId > $this->maxWorkerId || $workerId < 0) { throw new Exception("workerId 不能大于 maxWorkerId 或小于 0"); } $this->datacenterId = $datacenterId; $this->workerId = $workerId; } public function nextId() { $timestamp = $this->timeGen(); if ($timestamp < $this->lastTimestamp) { throw new Exception("时钟向后移动。拒绝生成 ID"); } if ($this->lastTimestamp == $timestamp) { $this->sequence = ($this->sequence + 1) & $this->sequenceMask; if ($this->sequence == 0) { $timestamp = $this->tilNextMillis($this->lastTimestamp); } } else { $this->sequence = 0; } $this->lastTimestamp