เครื่องสร้างและวิเคราะห์ ID Snowflake ของ Twitter
สร้างและวิเคราะห์ ID Snowflake ของ Twitter ซึ่งเป็นตัวระบุที่ไม่ซ้ำกัน 64 บิตที่ใช้ในระบบกระจาย เครื่องมือนี้ช่วยให้คุณสร้าง ID Snowflake ใหม่และแยกวิเคราะห์ ID ที่มีอยู่ โดยให้ข้อมูลเชิงลึกเกี่ยวกับส่วนประกอบของเวลา เครื่อง ID และหมายเลขลำดับ
ตัวสร้าง ID Snowflake
ตัวสร้าง ID Snowflake
เอกสารประกอบ
Snowflake ID Generator
Introduction
Snowflake ID เป็นตัวระบุที่ไม่ซ้ำกันซึ่งใช้ในระบบกระจาย โดยพัฒนาโดย Twitter เครื่องมือนี้ช่วยให้คุณสามารถสร้างและวิเคราะห์ Snowflake IDs ซึ่งเป็นจำนวนเต็ม 64 บิตที่ประกอบด้วย timestamp, machine ID และ sequence number
How Snowflake IDs Work
Snowflake IDs เป็นจำนวนเต็ม 64 บิตที่มีโครงสร้างดังนี้:
- 41 บิต: Timestamp (มิลลิวินาทีตั้งแต่ยุคที่กำหนด)
- 10 บิต: Machine ID (5 บิตสำหรับ data center ID, 5 บิตสำหรับ worker ID)
- 12 บิต: Sequence number
โครงสร้างนี้ช่วยให้สามารถสร้าง ID ที่ไม่ซ้ำกันได้ประมาณ 4,096 ID ต่อมิลลิวินาทีต่อเครื่อง
Using the Snowflake ID Generator
- (ไม่บังคับ) ตั้งค่า epoch ที่กำหนดเอง (ค่าเริ่มต้นคือ epoch ของ Twitter: 2010-11-04T01:42:54.657Z)
- ป้อน machine ID (0-31) และ data center ID (0-31)
- คลิก "Generate" เพื่อสร้าง Snowflake ID ใหม่
- ID ที่สร้างขึ้นและส่วนประกอบของมันจะแสดง
ในการวิเคราะห์ Snowflake ID ที่มีอยู่ ให้ป้อน ID ในช่อง "Parse ID" และคลิก "Parse"
Formula
Snowflake ID ถูกสร้างขึ้นโดยใช้การดำเนินการแบบ bitwise:
1ID = (timestamp << 22) | (datacenterId << 17) | (workerId << 12) | sequence
2
โดยที่:
timestamp
คือจำนวนมิลลิวินาทีตั้งแต่ยุคdatacenterId
คือจำนวนเต็ม 5 บิต (0-31)workerId
คือจำนวนเต็ม 5 บิต (0-31)sequence
คือจำนวนเต็ม 12 บิต (0-4095)
Calculation
ตัวสร้าง Snowflake ID ทำตามขั้นตอนดังต่อไปนี้:
- รับ timestamp ปัจจุบันในมิลลิวินาที
- ตรวจสอบให้แน่ใจว่า timestamp มากกว่าตัว timestamp ที่ใช้ล่าสุด (เพื่อความไม่ซ้ำกัน)
- หาก timestamp เท่ากับตัวล่าสุด ให้เพิ่ม sequence number
- หาก sequence number เกินขอบเขต (ถึง 4096) ให้รอจนถึงมิลลิวินาทีถัดไป
- รวมส่วนประกอบโดยใช้การดำเนินการแบบ bitwise เพื่อสร้าง ID สุดท้าย
Use Cases
Snowflake IDs มีประโยชน์โดยเฉพาะใน:
- ระบบกระจาย: สร้าง ID ที่ไม่ซ้ำกันทั่วหลายเครื่องโดยไม่ต้องประสาน
- ข้อมูลปริมาณสูง: สร้าง ID ที่สามารถเรียงลำดับได้สำหรับชุดข้อมูลขนาดใหญ่
- Microservices: รับประกันตัวระบุที่ไม่ซ้ำกันในบริการต่างๆ
- Database Sharding: ใช้ส่วนประกอบ timestamp หรือ machine ID สำหรับการแบ่งข้อมูลอย่างมีประสิทธิภาพ
Alternatives
แม้ว่า Snowflake IDs จะมีพลัง แต่ระบบการสร้าง ID อื่นๆ ได้แก่:
- UUID (Universally Unique Identifier): มีประโยชน์เมื่อจำเป็นต้องสร้างแบบกระจายโดยไม่มีการเรียงลำดับ
- Auto-incrementing database IDs: ง่ายแต่จำกัดอยู่ที่อินสแตนซ์ฐานข้อมูลเดียว
- ULID (Universally Unique Lexicographically Sortable Identifier): คล้ายกับ Snowflake แต่มีโครงสร้างที่แตกต่างกัน
Edge Cases and Limitations
-
การซิงโครไนซ์นาฬิกา: Snowflake IDs ขึ้นอยู่กับเวลาในระบบ หากนาฬิกาย้อนกลับเนื่องจากการปรับ NTP หรือการเปลี่ยนเวลาในฤดู จะทำให้เกิดปัญหาในการสร้าง ID
-
ปัญหาปี 2038: timestamp 41 บิตจะล้นในปี 2079 (สมมติว่าเป็น epoch ของ Twitter) ระบบที่ใช้ Snowflake IDs ควรวางแผนสำหรับเหตุการณ์นี้
-
การชนกันของ Machine ID: ในระบบกระจายขนาดใหญ่ การรับประกันว่า machine IDs ไม่ซ้ำกันอาจเป็นเรื่องท้าทายและอาจต้องการการประสานงานเพิ่มเติม
-
การล้นของ Sequence: ในสถานการณ์ที่มีการส่งข้อมูลสูงมาก อาจมีความเป็นไปได้ที่จะใช้ sequence 4096 ต่อมิลลิวินาทีจนหมด ซึ่งอาจทำให้เกิดความล่าช้า
-
การไม่เป็นระเบียบในหลายเครื่อง: แม้ว่า IDs จะเพิ่มขึ้นอย่างต่อเนื่องในเครื่องเดียว แต่ก็อาจไม่เป็นระเบียบอย่างเคร่งครัดในหลายเครื่อง
History
Snowflake IDs ถูกนำเสนอโดย Twitter ในปี 2010 เพื่อแก้ปัญหาความต้องการตัวระบุที่ไม่ซ้ำกันและสามารถเรียงลำดับเวลาได้ในระบบกระจาย ตั้งแต่นั้นมาได้มีการนำไปใช้และปรับปรุงโดยบริษัทและโครงการอื่นๆ หลายแห่ง
Examples
นี่คือตัวอย่างการสร้าง Snowflake 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(`Snowflake 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"Snowflake 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 can't be greater than maxDatacenterId or less than 0");
39 }
40 if (workerId > maxWorkerId || workerId < 0) {
41 throw new IllegalArgumentException("workerId can't be greater than maxWorkerId or less than 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("Snowflake 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
23 @lock = Mutex.new
24 end
25
26 def next_id
27 @lock.synchronize do
28 timestamp = (Time.now.to_f * 1000).to_i
29
30 raise 'นาฬิกาย้อนกลับ' if timestamp < @last_timestamp
31
32 if timestamp == @last_timestamp
33 @sequence = (@sequence + 1) & @sequence_mask
34 timestamp = til_next_millis(@last_timestamp) if @sequence == 0
35 else
36 @sequence = 0
37 end
38
39 @last_timestamp = timestamp
40
41 ((timestamp - @epoch) << @timestamp_left_shift) |
42 (@datacenter_id << @datacenter_id_shift) |
43 (@worker_id << @worker_id_shift) |
44 @sequence
45 end
46 end
47
48 private
49
50 def til_next_millis(last_timestamp)
51 timestamp = (Time.now.to_f * 1000).to_i
52 timestamp = (Time.now.to_f * 1000).to_i while timestamp <= last_timestamp
53 timestamp
54 end
55end
56
57## การใช้งาน
58generator = SnowflakeGenerator.new(1, 1)
59snowflake_id = generator.next_id
60puts "Snowflake ID ที่สร้างขึ้น: #{snowflake_id}"
61
1<?php
2
3class SnowflakeGenerator {
4 private $epoch;
5 private $datacenterIdBits;
6 private $workerIdBits;
7 private $sequenceBits;
8 private $maxDatacenterId;
9 private $maxWorkerId;
10 private $workerIdShift;
11 private $datacenterIdShift;
12 private $timestampLeftShift;
13 private $sequenceMask;
14
15 private $datacenterId;
16 private $workerId;
17 private $sequence = 0;
18 private $lastTimestamp = -1;
19
20 public function __construct($datacenterId, $workerId) {
21 $this->epoch = 1288834974657;
22 $this->datacenterIdBits = 5;
23 $this->workerIdBits = 5;
24 $this->sequenceBits = 12;
25
26 $this->maxDatacenterId = -1 ^ (-1 << $this->datacenterIdBits);
27 $this->maxWorkerId = -1 ^ (-1 << $this->workerIdBits);
28
29 $this->workerIdShift = $this->sequenceBits;
30 $this->datacenterIdShift = $this->sequenceBits + $this->workerIdBits;
31 $this->timestampLeftShift = $this->sequenceBits + $this->workerIdBits + $this->datacenterIdBits;
32 $this->sequenceMask = -1 ^ (-1 << $this->sequenceBits);
33
34 if ($datacenterId > $this->maxDatacenterId || $datacenterId < 0) {
35 throw new Exception("datacenterId can't be greater than maxDatacenterId or less than 0");
36 }
37 if ($workerId > $this->maxWorkerId || $workerId < 0) {
38 throw new Exception("workerId can't be greater than maxWorkerId or less than 0");
39 }
40 $this->datacenterId = $datacenterId;
41 $this->workerId = $workerId;
42 }
43
44 public function nextId() {
45 $timestamp = $this->timeGen();
46
47 if ($timestamp < $this->lastTimestamp) {
48 throw new Exception("นาฬิกาย้อนกลับ ปฏิเสธที่จะสร้าง id");
49 }
50
51 if ($this->lastTimestamp == $timestamp) {
52 $this->sequence = ($this->sequence + 1) & $this->sequenceMask;
53 if ($this->sequence == 0) {
54 $timestamp = $this->tilNextMillis($this->lastTimestamp);
55 }
56 } else {
57 $this->sequence = 0;
58 }
59
60 $this->lastTimestamp = $timestamp;
61
62 return (($timestamp - $this->epoch) << $this->timestampLeftShift) |
63 ($this->datacenterId << $this->datacenterIdShift) |
64 ($this->workerId << $this->workerIdShift) |
65 $this->sequence;
66 }
67
68 private function tilNextMillis($lastTimestamp) {
69 $timestamp = $this->timeGen();
70 while ($timestamp <= $lastTimestamp) {
71 $timestamp = $this->timeGen();
72 }
73 return $timestamp;
74 }
75
76 private function timeGen() {
77 return floor(microtime(true) * 1000);
78 }
79}
80
81// การใช้งาน
82$generator = new SnowflakeGenerator(1, 1);
83$id = $generator->nextId();
84echo "Snowflake ID ที่สร้างขึ้น: " . $id . "\n";
85
1using System;
2using System.Threading;
3
4public class SnowflakeGenerator
5{
6 private readonly long _epoch;
7 private readonly int _datacenterIdBits;
8 private readonly int _workerIdBits;
9 private readonly int _sequenceBits;
10 private readonly long _maxDatacenterId;
11 private readonly long _maxWorkerId;
12 private readonly int _workerIdShift;
13 private readonly int _datacenterIdShift;
14 private readonly int _timestampLeftShift;
15 private readonly long _sequenceMask;
16
17 private readonly long _datacenterId;
18 private readonly long _workerId;
19 private long _sequence = 0L;
20 private long _lastTimestamp = -1L;
21
22 private readonly object _lock = new object();
23
24 public SnowflakeGenerator(long datacenterId, long workerId)
25 {
26 _epoch = 1288834974657L;
27 _datacenterIdBits = 5;
28 _workerIdBits = 5;
29 _sequenceBits = 12;
30
31 _maxDatacenterId = -1L ^ (-1L << _datacenterIdBits);
32 _maxWorkerId = -1L ^ (-1L << _workerIdBits);
33
34 _workerIdShift = _sequenceBits;
35 _datacenterIdShift = _sequenceBits + _workerIdBits;
36 _timestampLeftShift = _sequenceBits + _workerIdBits + _datacenterIdBits;
37 _sequenceMask = -1L ^ (-1L << _sequenceBits);
38
39 if (datacenterId > _maxDatacenterId || datacenterId < 0)
40 {
41 throw new ArgumentException($"datacenterId can't be greater than {_maxDatacenterId} or less than 0");
42 }
43 if (workerId > _maxWorkerId || workerId < 0)
44 {
45 throw new ArgumentException($"workerId can't be greater than {_maxWorkerId} or less than 0");
46 }
47 _datacenterId = datacenterId;
48 _workerId = workerId;
49 }
50
51 public long NextId()
52 {
53 lock (_lock)
54 {
55 var timestamp = TimeGen();
56
57 if (timestamp < _lastTimestamp)
58 {
59 throw new Exception("นาฬิกาย้อนกลับ ปฏิเสธที่จะสร้าง id");
60 }
61
62 if (_lastTimestamp == timestamp)
63 {
64 _sequence = (_sequence + 1) & _sequenceMask;
65 if (_sequence == 0)
66 {
67 timestamp = TilNextMillis(_lastTimestamp);
68 }
69 }
70 else
71 {
72 _sequence = 0L;
73 }
74
75 _lastTimestamp = timestamp;
76
77 return ((timestamp - _epoch) << _timestampLeftShift) |
78 (_datacenterId << _datacenterIdShift) |
79 (_workerId << _workerIdShift) |
80 _sequence;
81 }
82 }
83
84 private long TilNextMillis(long lastTimestamp)
85 {
86 var timestamp = TimeGen();
87 while (timestamp <= lastTimestamp)
88 {
89 timestamp = TimeGen();
90 }
91 return timestamp;
92 }
93
94 private long TimeGen()
95 {
96 return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
97 }
98}
99
100// การใช้งาน
101class Program
102{
103 static void Main(string[] args)
104 {
105 var generator = new SnowflakeGenerator(1, 1);
106 var id = generator.NextId();
107 Console.WriteLine($"Snowflake ID ที่สร้างขึ้น: {id}");
108 }
109}
110
1package main
2
3import (
4 "fmt"
5 "sync"
6 "time"
7)
8
9type SnowflakeGenerator struct {
10 epoch int64
11 datacenterIdBits uint
12 workerIdBits uint
13 sequenceBits uint
14 maxDatacenterId int64
15 maxWorkerId int64
16 workerIdShift uint
17 datacenterIdShift uint
18 timestampLeftShift uint
19 sequenceMask int64
20
21 datacenterId int64
22 workerId int64
23 sequence int64
24 lastTimestamp int64
25
26 lock sync.Mutex
27}
28
29func NewSnowflakeGenerator(datacenterId, workerId int64) (*SnowflakeGenerator, error) {
30 g := &SnowflakeGenerator{
31 epoch: 1288834974657,
32 datacenterIdBits: 5,
33 workerIdBits: 5,
34 sequenceBits: 12,
35 lastTimestamp: -1,
36 }
37
38 g.maxDatacenterId = -1 ^ (-1 << g.datacenterIdBits)
39 g.maxWorkerId = -1 ^ (-1 << g.workerIdBits)
40
41 g.workerIdShift = g.sequenceBits
42 g.datacenterIdShift = g.sequenceBits + g.workerIdBits
43 g.timestampLeftShift = g.sequenceBits + g.workerIdBits + g.datacenterIdBits
44 g.sequenceMask = -1 ^ (-1 << g.sequenceBits)
45
46 if datacenterId > g.maxDatacenterId || datacenterId < 0 {
47 return nil, fmt.Errorf("datacenterId can't be greater than %d or less than 0", g.maxDatacenterId)
48 }
49 if workerId > g.maxWorkerId || workerId < 0 {
50 return nil, fmt.Errorf("workerId can't be greater than %d or less than 0", g.maxWorkerId)
51 }
52 g.datacenterId = datacenterId
53 g.workerId = workerId
54
55 return g, nil
56}
57
58func (g *SnowflakeGenerator) NextId() (int64, error) {
59 g.lock.Lock()
60 defer g.lock.Unlock()
61
62 timestamp := g.timeGen()
63
64 if timestamp < g.lastTimestamp {
65 return 0, fmt.Errorf("นาฬิกาย้อนกลับ ปฏิเสธที่จะสร้าง id")
66 }
67
68 if g.lastTimestamp == timestamp {
69 g.sequence = (g.sequence + 1) & g.sequenceMask
70 if g.sequence == 0 {
71 timestamp = g.tilNextMillis(g.lastTimestamp)
72 }
73 } else {
74 g.sequence = 0
75 }
76
77 g.lastTimestamp = timestamp
78
79 return ((timestamp - g.epoch) << g.timestampLeftShift) |
80 (g.datacenterId << g.datacenterIdShift) |
81 (g.workerId << g.workerIdShift) |
82 g.sequence, nil
83}
84
85func (g *SnowflakeGenerator) tilNextMillis(lastTimestamp int64) int64 {
86 timestamp := g.timeGen()
87 for timestamp <= lastTimestamp {
88 timestamp = g.timeGen()
89 }
90 return timestamp
91}
92
93func (g *SnowflakeGenerator) timeGen() int64 {
94 return time.Now().UnixNano() / int64(time.Millisecond)
95}
96
97func main() {
98 generator, err := NewSnowflakeGenerator(1, 1)
99 if err != nil {
100 fmt.Printf("เกิดข้อผิดพลาดในการสร้างตัวสร้าง: %v\n", err)
101 return
102 }
103
104 id, err := generator.NextId()
105 if err != nil {
106 fmt.Printf("เกิดข้อผิดพลาดในการสร้าง ID: %v\n", err)
107 return
108 }
109
110 fmt.Printf("Snowflake ID ที่สร้างขึ้น: %d\n", id)
111}
112
Diagram
นี่คือการแสดงภาพโครงสร้างของ Snowflake ID:
References
- "ประกาศ Snowflake." บล็อกวิศวกรรมของ Twitter, https://blog.twitter.com/engineering/en_us/a/2010/announcing-snowflake
- "Snowflake ID." วิกิพีเดีย, https://th.wikipedia.org/wiki/Snowflake_ID
- "การสร้าง ID แบบกระจายใน Microservices." Medium, https://medium.com/swlh/distributed-id-generation-in-microservices-b6ce9a8dd93f
ข้อเสนอแนะแสดงความคิดเห็น
คลิกที่ข้อเสนอแนะแสดงความคิดเห็นเพื่อเริ่มให้ข้อเสนอแนะแก่เครื่องมือนี้
เครื่องมือที่เกี่ยวข้อง
ค้นพบเครื่องมือเพิ่มเติมที่อาจมีประโยชน์สำหรับการทำงานของคุณ