Γεννήτρια Snowflake IDs για κατανεμημένα συστήματα
Δημιουργήστε και αναλύστε τα Twitter Snowflake IDs, μοναδικούς 64-bit αναγνωριστικούς αριθμούς που χρησιμοποιούνται σε κατανεμημένα συστήματα. Αυτό το εργαλείο σας επιτρέπει να δημιουργείτε νέα Snowflake IDs και να αναλύετε υπάρχοντα, παρέχοντας πληροφορίες σχετικά με τα συστατικά τους, όπως χρονική σήμανση, αναγνωριστικό μηχανής και αριθμό ακολουθίας.
Γεννήτρια ID Snowflake
Γεννήτρια ID Snowflake
Τεκμηρίωση
Snowflake ID Generator
Εισαγωγή
Ένα Snowflake ID είναι ένας μοναδικός αναγνωριστικός αριθμός που χρησιμοποιείται σε κατανεμημένα συστήματα, που αναπτύχθηκε αρχικά από το Twitter. Αυτό το εργαλείο σας επιτρέπει να δημιουργείτε και να αναλύετε Snowflake IDs, τα οποία είναι 64-bit ακέραιοι αριθμοί που αποτελούνται από ένα χρονοσφραγίδα, αναγνωριστικό μηχανής και αριθμό ακολουθίας.
Πώς λειτουργούν τα Snowflake IDs
Τα Snowflake IDs είναι 64-bit ακέραιοι αριθμοί που δομούνται ως εξής:
- 41 bits: Χρονοσφραγίδα (χιλιοστά από μια προσαρμοσμένη εποχή)
- 10 bits: Αναγνωριστικό μηχανής (5 bits για το αναγνωριστικό κέντρου δεδομένων, 5 bits για το αναγνωριστικό εργαζομένου)
- 12 bits: Αριθμός ακολουθίας
Αυτή η δομή επιτρέπει τη δημιουργία περίπου 4.096 μοναδικών IDs ανά χιλιοστά του δευτερολέπτου ανά μηχανή.
Χρήση του Snowflake ID Generator
- (Προαιρετικά) Ρυθμίστε μια προσαρμοσμένη εποχή (η προεπιλογή είναι η εποχή του Twitter: 2010-11-04T01:42:54.657Z)
- Εισάγετε ένα αναγνωριστικό μηχανής (0-31) και αναγνωριστικό κέντρου δεδομένων (0-31)
- Κάντε κλικ στο "Δημιουργία" για να δημιουργήσετε ένα νέο Snowflake ID
- Το παραγόμενο ID και τα συστατικά του θα εμφανιστούν
Για να αναλύσετε ένα υπάρχον Snowflake ID, εισάγετε το στο πεδίο "Ανάλυση ID" και κάντε κλικ στο "Ανάλυση".
Τύπος
Το Snowflake ID κατασκευάζεται χρησιμοποιώντας bitwise operations:
1ID = (timestamp << 22) | (datacenterId << 17) | (workerId << 12) | sequence
2
Όπου:
timestamp
είναι ο αριθμός χιλιοστών από την εποχήdatacenterId
είναι ένας 5-bit ακέραιος αριθμός (0-31)workerId
είναι ένας 5-bit ακέραιος αριθμός (0-31)sequence
είναι ένας 12-bit ακέραιος αριθμός (0-4095)
Υπολογισμός
Ο γεννήτορας Snowflake ID εκτελεί τα εξής βήματα:
- Λάβετε την τρέχουσα χρονοσφραγίδα σε χιλιοστά
- Βεβαιωθείτε ότι η χρονοσφραγίδα είναι μεγαλύτερη από την τελευταία χρησιμοποιούμενη χρονοσφραγίδα (για μοναδικότητα)
- Εάν η χρονοσφραγίδα είναι η ίδια με την τελευταία, αυξήστε τον αριθμό ακολουθίας
- Εάν ο αριθμός ακολουθίας υπερχειλίσει (φτάσει το 4096), περιμένετε για την επόμενη χιλιοστά
- Συνδυάστε τα συστατικά χρησιμοποιώντας bitwise operations για να δημιουργήσετε το τελικό ID
Χρήσεις
Τα Snowflake IDs είναι ιδιαίτερα χρήσιμα σε:
- Κατανεμημένα Συστήματα: Δημιουργία μοναδικών IDs σε πολλές μηχανές χωρίς συντονισμό
- Υψηλού Όγκου Δεδομένα: Δημιουργία ταξινομήσιμων IDs για μεγάλες βάσεις δεδομένων
- Μικροϋπηρεσίες: Διασφάλιση μοναδικών αναγνωριστικών σε διάφορες υπηρεσίες
- Κατανομή Βάσεων Δεδομένων: Χρήση του χρονοσφραγίδας ή του συστατικού αναγνωριστικού μηχανής για αποδοτική κατανομή
Εναλλακτικές
Ενώ τα Snowflake IDs είναι ισχυρά, άλλα συστήματα δημιουργίας ID περιλαμβάνουν:
- UUID (Καθολικά Μοναδικός Αναγνωριστικός Αριθμός): Χρήσιμο όταν απαιτείται κατανεμημένη δημιουργία χωρίς ταξινομησιμότητα
- Αυτόματοι αυξανόμενοι αναγνωριστικοί αριθμοί βάσεων δεδομένων: Απλοί αλλά περιορισμένοι σε μεμονωμένα παραδείγματα βάσεων δεδομένων
- ULID (Καθολικά Μοναδικά Ταξινομήσιμα Αναγνωριστικά): Παρόμοια με τα Snowflake, αλλά με διαφορετική δομή
Άκρα Περίπτωση και Περιορισμοί
-
Συγχρονισμός Ρολογιού: Τα Snowflake IDs βασίζονται στον χρόνο του συστήματος. Εάν το ρολόι μετακινηθεί προς τα πίσω λόγω ρυθμίσεων NTP ή αλλαγών ώρας θερινής ώρας, μπορεί να προκαλέσει προβλήματα στη δημιουργία ID.
-
Πρόβλημα Έτους 2038: Ο 41-bit χρονοσφραγίδας θα υπερχειλίσει το 2079 (υποθέτοντας την εποχή του Twitter). Τα συστήματα που χρησιμοποιούν Snowflake IDs θα πρέπει να σχεδιάσουν για αυτή την eventuality.
-
Συγκρούσεις Αναγνωριστικού Μηχανής: Σε μεγάλα κατανεμημένα συστήματα, η διασφάλιση μοναδικών αναγνωριστικών μηχανών μπορεί να είναι δύσκολη και μπορεί να απαιτεί πρόσθετο συντονισμό.
-
Υπερχειλία Ακολουθίας: Σε εξαιρετικά υψηλής ροής σενάρια, είναι δυνατό να εξαντληθούν οι 4096 ακολουθίες ανά χιλιοστά, ενδεχομένως προκαλώντας καθυστερήσεις.
-
Μη Μονοτονία σε Πολλές Μηχανές: Ενώ τα IDs είναι μονοτονικά αυξανόμενα σε μια μόνο μηχανή, μπορεί να μην είναι αυστηρά μονοτονικά σε πολλές μηχανές.
Ιστορία
Τα Snowflake IDs εισήχθησαν από το Twitter το 2010 για να καλύψουν την ανάγκη για κατανεμημένα, ταξινομήσιμα μοναδικά αναγνωριστικά. Έχουν από τότε υιοθετηθεί και προσαρμοστεί από πολλές άλλες εταιρείες και έργα.
Παραδείγματα
Ακολουθούν υλοποιήσεις γεννητριών 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('Clock moved backwards. Refusing to generate 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(`Generated 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("Clock moved backwards. Refusing to generate 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"Generated 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("Clock moved backwards. Refusing to generate 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("Generated 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 @datacenter_id_bits = 5
11 @worker_id_bits = 5
12 @sequence_bits = 12
13 @max_datacenter_id = -1 ^ (-1 << @datacenter_id_bits)
14 @max_worker_id = -1 ^ (-1 << @worker_id_bits)
15 @worker_id_shift = @sequence_bits
16 @datacenter_id_shift = @sequence_bits + @worker_id_bits
17 @timestamp_left_shift = @sequence_bits + @worker_id_bits + @datacenter_id_bits
18 @sequence_mask = -1 ^ (-1 << @sequence_bits)
19 @lock = Mutex.new
20 end
21
22 def next_id
23 @lock.synchronize do
24 timestamp = (Time.now.to_f * 1000).to_i
25 raise 'Clock moved backwards' if timestamp < @last_timestamp
26
27 if timestamp == @last_timestamp
28 @sequence = (@sequence + 1) & @sequence_mask
29 timestamp = til_next_millis(@last_timestamp) if @sequence == 0
30 else
31 @sequence = 0
32 end
33
34 @last_timestamp = timestamp
35
36 ((timestamp - @epoch) << @timestamp_left_shift) |
37 (@datacenter_id << @datacenter_id_shift) |
38 (@worker_id << @worker_id_shift) |
39 @sequence
40 end
41 end
42
43 private
44
45 def til_next_millis(last_timestamp)
46 timestamp = (Time.now.to_f * 1000).to_i
47 timestamp = (Time.now.to_f * 1000).to_i while timestamp <= last_timestamp
48 timestamp
49 end
50end
51
52## Χρήση
53generator = SnowflakeGenerator.new(1, 1)
54snowflake_id = generator.next_id
55puts "Generated Snowflake ID: #{snowflake_id}"
56
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("Clock moved backwards. Refusing to generate 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 "Generated 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("Clock moved backwards. Refusing to generate 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($"Generated 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("clock moved backwards, refusing to generate 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("Error creating generator: %v\n", err)
101 return
102 }
103
104 id, err := generator.NextId()
105 if err != nil {
106 fmt.Printf("Error generating ID: %v\n", err)
107 return
108 }
109
110 fmt.Printf("Generated Snowflake ID: %d\n", id)
111}
112
Διάγραμμα
Ακολουθεί μια οπτική αναπαράσταση της δομής του Snowflake ID:
Αναφορές
- "Ανακοίνωση Snowflake." Blog Μηχανικής Twitter, https://blog.twitter.com/engineering/en_us/a/2010/announcing-snowflake
- "Snowflake ID." Wikipedia, https://en.wikipedia.org/wiki/Snowflake_ID
- "Κατανεμημένη Δημιουργία ID σε Μικροϋπηρεσίες." Medium, https://medium.com/swlh/distributed-id-generation-in-microservices-b6ce9a8dd93f
Ανατροφοδότηση
Κάντε κλικ στο toast ανατροφοδότησης για να ξεκινήσετε να δίνετε ανατροφοδότηση για αυτό το εργαλείο
Σχετικά Εργαλεία
Ανακαλύψτε περισσότερα εργαλεία που μπορεί να είναι χρήσιμα για τη ροή εργασίας σας