Генератор на Snowflake ID
Генератор на Snowflake ID
Генератор на Snowflake ID
Въведение
Snowflake ID е уникален идентификатор, използван в разпределени системи, първоначално разработен от Twitter. Този инструмент ви позволява да генерирате и анализирате Snowflake ID, които са 64-битови цели числа, съставени от времеви печат, идентификатор на машина и номер на последователност.
Как работят Snowflake ID
Snowflake ID са 64-битови цели числа, структурирани по следния начин:
- 41 бит: Времеви печат (милисекунди от собствена епоха)
- 10 бита: Идентификатор на машина (5 бита за идентификатор на дата център, 5 бита за идентификатор на работник)
- 12 бита: Номер на последователност
Тази структура позволява генерирането на приблизително 4,096 уникални ID на милисекунда на машина.
Използване на генератора на Snowflake ID
- (По избор) Задайте собствена епоха (по подразбиране е епохата на Twitter: 2010-11-04T01:42:54.657Z)
- Въведете идентификатор на машина (0-31) и идентификатор на дата център (0-31)
- Щракнете върху "Генерирай", за да създадете нов Snowflake ID
- Генерираният ID и неговите компоненти ще бъдат показани
За да анализирате съществуващ Snowflake ID, въведете го в полето "Анализиране на ID" и щракнете върху "Анализиране".
Формула
Snowflake ID се конструира с помощта на битови операции:
ID = (timestamp << 22) | (datacenterId << 17) | (workerId << 12) | sequence
Където:
timestamp
е броят на милисекундите от епохатаdatacenterId
е 5-битов цяло число (0-31)workerId
е 5-битов цяло число (0-31)sequence
е 12-битов цяло число (0-4095)
Изчисление
Генераторът на Snowflake ID извършва следните стъпки:
- Вземете текущия времеви печат в милисекунди
- Уверете се, че времевият печат е по-голям от последния използван времеви печат (за уникалност)
- Ако времевият печат е същият като последния, увеличете номера на последователността
- Ако номерът на последователността прелее (достигне 4096), изчакайте следващата милисекунда
- Комбинирайте компонентите с помощта на битови операции, за да създадете окончателния ID
Случаи на употреба
Snowflake ID са особено полезни в:
- Разпределени системи: Генерирайте уникални ID на множество машини без координация
- Високобройни данни: Създайте сортиращи ID за големи набори от данни
- Микросервизи: Осигурете уникални идентификатори между различни услуги
- Разделяне на бази данни: Използвайте времевия печат или компонента на идентификатора на машината за ефективно разделяне
Алтернативи
Докато Snowflake ID са мощни, други системи за генериране на ID включват:
- UUID (Универсален уникален идентификатор): Полезен, когато е необходимо разпределено генериране без сортиране
- Автоинкрементни идентификатори на бази данни: Прости, но ограничени до единични инстанции на бази данни
- ULID (Универсален уникален лексикографски сортиран идентификатор): Подобен на Snowflake, но с различна структура
Гранични случаи и ограничения
-
Синхронизация на часовника: Snowflake ID разчитат на системното време. Ако часовникът се върне назад поради корекции на NTP или промени в лятното часово време, това може да предизвика проблеми с генерирането на ID.
-
Проблемът с годината 2038: 41-битовият времеви печат ще прелее през 2079 (при условие, че епохата на Twitter). Системите, използващи Snowflake ID, трябва да планират за това.
-
Колизии на идентификаторите на машините: В големи разпределени системи, осигуряването на уникални идентификатори на машините може да бъде предизвикателство и може да изисква допълнителна координация.
-
Преливане на последователността: В изключително високообемни сценарии е възможно да се изчерпат 4096 последователности на милисекунда, което потенциално да предизвика забавяния.
-
Ненадеждност на последователността между машините: Докато ID са монотонно нарастващи на една машина, те може да не са строго монотонни между множество машини.
История
Snowflake ID бяха въведени от Twitter през 2010 г. с цел да се задоволи нуждата от разпределени, времево-сортирани уникални идентификатори. Те оттогава са приети и адаптирани от много други компании и проекти.
Примери
Ето реализации на генератори на Snowflake ID на различни езици:
class SnowflakeGenerator {
constructor(epoch = 1288834974657, datacenterIdBits = 5, workerIdBits = 5, sequenceBits = 12) {
this.epoch = BigInt(epoch);
this.datacenterIdBits = datacenterIdBits;
this.workerIdBits = workerIdBits;
this.sequenceBits = sequenceBits;
this.maxDatacenterId = -1n ^ (-1n << BigInt(datacenterIdBits));
this.maxWorkerId = -1n ^ (-1n << BigInt(workerIdBits));
this.sequenceMask = -1n ^ (-1n << BigInt(sequenceBits));
this.workerIdShift = BigInt(sequenceBits);
this.datacenterIdShift = BigInt(sequenceBits + workerIdBits);
this.timestampLeftShift = BigInt(sequenceBits + workerIdBits + datacenterIdBits);
this.sequence = 0n;
this.lastTimestamp = -1n;
}
nextId(datacenterId, workerId) {
let timestamp = this.currentTimestamp();
if (timestamp < this.lastTimestamp) {
throw new Error('Часовникът се е преместил назад. Отказвам да генерирам ID');
}
if (timestamp === this.lastTimestamp) {
this.sequence = (this.sequence + 1n) & this.sequenceMask;
if (this.sequence === 0n) {
timestamp = this.tilNextMillis(this.lastTimestamp);
}
} else {
this.sequence = 0n;
}
this.lastTimestamp = timestamp;
return ((timestamp - this.epoch) << this.timestampLeftShift) |
(BigInt(datacenterId) << this.datacenterIdShift) |
(BigInt(workerId) << this.workerIdShift) |
this.sequence;
}
tilNextMillis(lastTimestamp) {
let timestamp = this.currentTimestamp();
while (timestamp <= lastTimestamp) {
timestamp = this.currentTimestamp();
}
return timestamp;
}
currentTimestamp() {
return BigInt(Date.now());
}
}
// Използване
const generator = new SnowflakeGenerator();
const id = generator.nextId(1, 1);
console.log(`Генериран Snowflake ID: ${id}`);
Диаграма
Ето визуално представяне на структурата на Snowflake ID:
Референции
- "Обявяване на Snowflake." Блог на Twitter Engineering, https://blog.twitter.com/engineering/en_us/a/2010/announcing-snowflake
- "Snowflake ID." Уикипедия, https://en.wikipedia.org/wiki/Snowflake_ID
- "Разпределено генериране на ID в микросервизи." Medium, https://medium.com/swlh/distributed-id-generation-in-microservices-b6ce9a8dd93f