Als Antwort auf die Leistungsfragen, die während der Verwendung häufig auftreten, gebe ich die folgenden drei Best Practices:
❄ Wenn die ID-Generierungsanforderung 5 W/s nicht überschreitet, müssen keine Konfigurationsparameter geändert werden.
❄ Wenn es 5 W Stück/s überschreitet und weniger als 50 W Stück/s beträgt, wird empfohlen, Folgendes zu ändern: SeqBitLength=10
❄ Wenn es 50 W Bits/s überschreitet und nahe bei 500 W Bits/s liegt, wird empfohlen, Folgendes zu ändern: SeqBitLength=12
Zusammenfassend lässt sich sagen, dass eine Erhöhung von SeqBitLength zu einer besseren Leistung führt, die generierten IDs jedoch länger sind.
❄ Hierbei handelt es sich um einen optimierten Schneeflocken-Algorithmus (Schneeflockendrift), der kürzere und schnellere IDs generiert.
❄ Unterstützt die automatische Erweiterung von Containerumgebungen wie k8s (automatische Registrierung von WorkerId) und kann eine digitale eindeutige ID in einer eigenständigen oder verteilten Umgebung generieren.
❄ Unterstützt nativ C#/Java/Go/C/Rust/Python/Node.js/PHP (C-Erweiterung)/SQL/ und andere Sprachen und bietet sicheres dynamisches Aufrufen dynamischer Bibliotheken (FFI) mit mehreren Threads.
❄ Kompatibel mit allen Snowflake-Algorithmen (Zahlensegmentmodus oder klassischer Modus, große oder kleine Hersteller), Sie können in Zukunft jedes Upgrade oder jeden Wechsel durchführen.
❄ Dies ist das umfassendste Tool zur Snowflake-ID-Generierung in der Computergeschichte. 【Stand August 2022】
?Als Architekt möchten Sie das Problem eindeutiger Primärschlüssel in einer Datenbank lösen, insbesondere in einem verteilten System mit mehreren Datenbanken.
? Sie möchten, dass der Primärschlüssel der Datentabelle den geringsten Speicherplatz beansprucht, schneller indiziert und schneller ausgewählt, eingefügt und aktualisiert wird.
?Sie sollten bedenken, dass beim Teilen von Datenbanken und Tabellen (Zusammenführen von Datenbanken und Tabellen) der Primärschlüsselwert direkt verwendet werden kann und das Geschäftstiming widerspiegeln kann.
?Wenn ein solcher Primärschlüsselwert zu lang ist und den Maximalwert des Front-End-JS-Zahlentyps überschreitet, muss der Long-Typ in den String-Typ konvertiert werden, und Sie werden ein wenig frustriert sein.
Obwohl Guid automatisch inkrementieren kann, nimmt es viel Platz ein und die Indizierungsgeschwindigkeit ist langsam. Sie möchten es nicht verwenden.
? Es können mehr als 50 Anwendungsinstanzen vorhanden sein und jede gleichzeitige Anfrage kann 10 W/s erreichen.
? Um Anwendungen in einer Containerumgebung bereitzustellen, unterstützen Sie horizontale Replikation und automatische Erweiterung.
? Sie möchten sich nicht auf die automatische Inkrementierung von Redis verlassen, um kontinuierliche Primärschlüssel-IDs zu erhalten, da kontinuierliche IDs ein Risiko für die Sicherheit von Geschäftsdaten darstellen.
? Sie möchten, dass das System länger als 100 Jahre funktioniert.
Die generierte ID ist zu lang.
Das Ausmaß der sofortigen Parallelität reicht nicht aus.
Das Zeitrückwahlproblem kann nicht gelöst werden.
Die nachträgliche Generierung der Vorbestellungs-ID wird nicht unterstützt.
Kann auf externe Speichersysteme zurückgreifen.
✔ Ganzzahlige Zahlen, die mit der Zeit monoton ansteigen (nicht unbedingt kontinuierlich), kürzer sind und den Maximalwert des js-Zahlentyps in 50 Jahren nicht überschreiten. (Standardkonfiguration)
✔ Schneller, 2-5 mal schneller als der herkömmliche Schneeflocken-Algorithmus, 500.000 können in 0,1 Sekunden generiert werden (basierend auf Niederspannungs-i7 der 8. Generation).
✔ Unterstützung der Rückrufverarbeitung. Wenn beispielsweise die Serverzeit um eine Sekunde zurückgesetzt wird, kann sich dieser Algorithmus automatisch anpassen, um eine eindeutige ID für die kritische Zeit zu generieren.
✔Unterstützt das manuelle Einfügen neuer IDs. Wenn das Unternehmen in historischer Zeit neue IDs generieren muss, können die reservierten Bits dieses Algorithmus 5.000 IDs pro Sekunde generieren.
✔ Verlässt sich nicht auf einen externen Cache oder eine externe Datenbank. (Die dynamische Bibliothek, die WorkerId automatisch in der k8s-Umgebung registriert, basiert auf Redis.)
✔ Grundfunktionen, sofort einsatzbereit, keine Konfigurationsdateien, Datenbankverbindungen etc. erforderlich.
(Parameter: 10-Bit-Sequenz mit automatischer Erhöhung, 1000 Drift-Maximalwerte)
Ständige Anfragen | 5K | 5W | 50W |
---|---|---|---|
Traditioneller Schneeflocken-Algorithmus | 0,0045s | 0,053 s | 0,556 s |
Schneedrift-Algorithmus | 0,0015s | 0,012 s | 0,113 s |
? Ultimative Leistung: 500 W/s ~ 3000 W/s. (Alle Testdaten wurden auf Basis des Niederspannungs-i7 der 8. Generation berechnet)
? Wenn der Systemzeit-Dialback erfolgt, verwendet der Algorithmus die reservierte Sequenznummer der vergangenen Zeitreihe, um eine neue ID zu generieren.
? Die durch den Rückruf generierte ID-Nummer wird standardmäßig an erster Stelle platziert und kann auch später angepasst werden.
? Ermöglichen, dass die Zeit auf die voreingestellte Basis dieses Algorithmus zurückgesetzt wird (Parameter sind einstellbar).
? Die von diesem Algorithmus generierte ID ist eine Ganzzahl (belegt bis zu 8 Byte Speicherplatz). Die folgende ID wird basierend auf der Standardkonfiguration generiert:
129053495681099 (运行1年,长度:15)
387750301904971 (运行3年,长度:15)
646093214093387 (运行5年,长度:15)
1292658282840139 (运行10年,长度:16)
9007199254740992 (运行70年,达到 js Number 最大值,长度:16)
165399880288699493 (运行1000年,等同普通雪花算法运行1年,长度:18)
?Der von diesem Algorithmus generierte ID-Wert beträgt 1 % bis 10 % des Maximalwerts von js. Dies ist ein Tausendstel des Werts des gewöhnlichen Schneeflockenalgorithmus, aber die Generierungsgeschwindigkeit ist schneller als die des gewöhnlichen Schneeflockenalgorithmus.
? Der Maximalwert des js-Zahlentyps: 9007199254740992. Es kann 70 Jahre dauern, bis dieser Algorithmus den js-Zahlenmaximumswert erreicht, während die Parallelitätsleistung (5 W+/0,01 s) und maximal 64 WorkerIds (6 Bit) aufrechterhalten werden.
? 每增加 1位 WorkerIdBitLength 或 SeqBitLength,生成的ID数字值将会乘以2(基础长度可参考前一节“ID示例”),反之则除以2。
Die Erklärung, wie lange es verwendet werden kann, bezieht sich darauf, wann die generierte ID-Nummer den Maximalwert von long (vorzeichenbehaftete 64 Bit, 8 Byte) überschreiten kann.
• In der Standardkonfiguration stehen 71000 eindeutige IDs zur Verfügung.
? Bei der Unterstützung von 1024 Worker-Knoten sind IDs 4480 Jahre lang ohne Duplizierung verfügbar.
? Bei der Unterstützung von 4096 Worker-Knoten sind IDs 1120 Jahre lang ohne Duplizierung verfügbar.
❄ WorkerIdBitLength , die Bitlänge des Maschinencodes, bestimmt den Maximalwert von WorkerId, der Standardwert ist 6 und der Wertebereich ist [1, 19]. Tatsächlich verwenden einige Sprachen den unsigned ushort (uint16)-Typ zum Empfangen Dieser Parameter beträgt daher der Maximalwert 16. Wenn Signed Short (int16) verwendet wird, beträgt der Maximalwert 15.
❄WorkerId , Maschinencode, der wichtigste Parameter , kein Standardwert, muss global eindeutig sein (oder innerhalb derselben DataCenterId eindeutig), muss programmgesteuert festgelegt werden , die Standardbedingung (WorkerIdBitLength nimmt den Standardwert an), der Maximalwert ist 63, Der theoretische Maximalwert beträgt 2^WorkerIdBitLength -1 (verschiedene Implementierungssprachen können auf 65535 oder 32767 begrenzt sein, das Prinzip ist das gleiche wie bei der WorkerIdBitLength-Regel). Er kann auf verschiedenen Maschinen oder Anwendungsinstanzen nicht gleich sein . Sie können diesen Wert über die Anwendung konfigurieren oder den Wert durch Aufrufen eines externen Dienstes erhalten. Als Reaktion auf die Notwendigkeit einer automatischen Registrierung von WorkerId bietet dieser Algorithmus eine Standardimplementierung: automatische Registrierung der dynamischen Bibliothek von WorkerId über Redis, Einzelheiten finden Sie unter „ToolsAutoRegisterWorkerId“.
Besonderer Hinweis : Wenn ein Server mehrere unabhängige Dienste bereitstellt, müssen Sie für jeden Dienst eine andere WorkerId angeben.
❄ SeqBitLength , Sequenzbitlänge, Standardwert 6 , Wertebereich [3, 21] (empfohlen nicht weniger als 4), bestimmt die Anzahl der pro Millisekunde generierten IDs. Wenn die Anzahl der Anfragen pro Sekunde 5 W nicht überschreitet, behalten Sie einfach den Standardwert von 6 bei. Wenn sie 5 W überschreitet und 50 W nicht überschreitet, wird empfohlen, einen Wert von 10 oder mehr zuzuweisen, und so weiter. Regelanforderung: WorkerIdBitLength + SeqBitLength überschreitet nicht 22.
❄ MinSeqNumber , minimale Sequenznummer, Standardwert 5, Wertebereich [5, MaxSeqNumber], die ersten 5 Sequenznummern pro Millisekunde entsprechen den Zahlen 0-4 sind reservierte Bits, von denen 1-4 reservierte Bits sind, die dem Zeitrückruf entsprechen, 0 ist ein reserviertes Bit für manuelle neue Werte.
❄ MaxSeqNumber , die maximale Sequenznummer, der Einstellbereich ist [MinSeqNumber, 2^SeqBitLength-1], der Standardwert ist 0, die tatsächliche maximale Sequenznummer ist der Maximalwert (2^SeqBitLength-1), wenn er nicht 0 ist Dies ist die tatsächliche maximale Sequenznummer und muss im Allgemeinen nicht festgelegt werden, es sei denn, mehrere Maschinen teilen sich die WorkerId, um IDs in Segmenten zu generieren (in diesem Fall muss die minimale Sequenznummer korrekt festgelegt werden).
❄ BaseTime , Basiszeit (auch bekannt als: Basispunktzeit, Ursprungszeit, Epochenzeit), hat einen Standardwert (2020), ist ein Millisekunden-Zeitstempel (eine Ganzzahl, .NET ist ein DatetTime-Typ), seine Funktion ist: Verwendung bei der Generierung der ID Als Zeitstempel für die Generierung der ID wird die Differenz (in Millisekunden) zwischen der Systemzeit und der Basiszeit verwendet. Es besteht im Allgemeinen keine Notwendigkeit, die Basiszeit festzulegen. Wenn Sie der Meinung sind, dass der Standardwert zu alt ist, können Sie ihn zurücksetzen. Bitte beachten Sie, dass es am besten ist, diesen Wert in Zukunft nicht mehr zu ändern.
Die zweite Version sieht vor, Parameter hinzuzufügen:
❄ DataCenterId , Rechenzentrums-ID (Computerraum-ID, Standard 0), bitte stellen Sie sicher, dass sie weltweit eindeutig ist.
❄ DataCenterIdBitLength , Länge der Rechenzentrums-ID (Standard 0).
❄ TimestampType , Zeitstempeltyp (0 Millisekunden, 1 Sekunde), Standard 0.
1️⃣ Rufen Sie im Singleton-Modus auf. Dieser Algorithmus verwendet einen einzelnen Thread zum Generieren von IDs, und Anrufe von mehreren Parteien schließen sich gegenseitig aus. Innerhalb derselben Anwendungsinstanz verwendet der Aufrufer Multithreading (oder Parallel), um diesen Algorithmus aufzurufen, wodurch die ID-Ausgabegeschwindigkeit nicht erhöht wird.
2️⃣ Geben Sie eine eindeutige WorkerId an. Das externe System muss die globale Eindeutigkeit der WorkerId sicherstellen und diese dem Eingabeparameter dieses Algorithmus zuweisen.
3️⃣ Verwenden Sie unterschiedliche WorkerIds, wenn Sie mehrere Instanzen auf einem einzelnen Computer bereitstellen. Nicht alle Implementierungen unterstützen prozessübergreifende gleichzeitige Eindeutigkeit. Um auf der sicheren Seite zu sein, stellen Sie bei der Bereitstellung mehrerer Anwendungsinstanzen auf demselben Host sicher, dass jede WorkerId eindeutig ist.
4️⃣ Ausnahmebehandlung. Der Algorithmus löst alle Ausnahmen aus, und das externe System sollte die Ausnahmen abfangen und gut behandeln, um einen größeren Systemabsturz zu vermeiden.
5️⃣ Machen Sie sich sorgfältig mit der Definition von IdGeneratorOptions vertraut, die für die Integration und Verwendung dieses Algorithmus hilfreich sein wird.
6️⃣ Verwenden Sie den Schneedrift-Algorithmus. Obwohl der Code die Definition des herkömmlichen Schneeflocken-Algorithmus enthält und Sie am Einstiegspunkt (Methode = 2) angeben können, um den herkömmlichen Algorithmus zu aktivieren, wird dennoch empfohlen, den Schneeflocken-Drift-Algorithmus zu verwenden (Methode = 1, Standard). Schließlich ist es besser dehnbar und leistungsstärker.
7️⃣ Ändern Sie den Kernalgorithmus nicht. Dieser Algorithmus verfügt über viele interne Parameter und eine komplexe Logik. Wenn Sie die Kernlogik nicht beherrschen, ändern Sie den Kerncode bitte nicht und verwenden Sie ihn nicht in einer Produktionsumgebung, es sei denn, er wurde durch eine große Anzahl sorgfältiger und wissenschaftlicher Tests verifiziert.
8️⃣ Die Konfigurationsrichtlinien innerhalb der Anwendungsdomäne sind dieselben. Wenn das System über einen längeren Zeitraum ausgeführt wurde und das Projekt von der programmgesteuerten Angabe von WorkerId auf die automatische Registrierung von WorkerId umstellen muss, stellen Sie bitte sicher, dass alle in derselben Anwendungsdomäne verwendeten Instanzen eine konsistente Konfigurationsstrategie anwenden. Dies gilt nicht nur für WorkerId , enthält aber auch andere Konfigurationsparameter.
9️⃣ Verwalten Sie die Serverzeit gut. Der Snowflake-Algorithmus ist auf die Systemzeit angewiesen. Passen Sie die Betriebssystemzeit nicht zu stark an. Wenn Sie Anpassungen vornehmen müssen, denken Sie daran, sicherzustellen, dass die Systemzeit beim erneuten Starten des Dienstes größer ist als die Zeit beim letzten Herunterfahren. (Hinweis: Kleine Änderungen der Systemzeit, die durch Zeitsynchronisierung oder Rückruf auf Weltklasse- oder Netzwerkebene verursacht werden, haben keinen Einfluss auf diesen Algorithmus.)
Bei Konfigurationsänderungen handelt es sich um die Anpassung der Betriebsparameter (IdGeneratorOptions-Objekteigenschaften), nachdem das System eine Zeit lang in Betrieb war. Bitte beachten Sie:
? 1. Das erste Prinzip lautet: BaseTime kann nur älter (weiter von der Gegenwart entfernt) sein , sodass der generierte ID-Wert größer als der historische Maximalwert ist, um sicherzustellen, dass es keine zeitliche Überschneidung gibt und keine doppelten IDs generiert werden. [ Es wird nicht empfohlen, BaseTime anzupassen, nachdem das System ausgeführt wurde]
? 2. Das Erhöhen von WorkerIdBitLength oder SeqBitLength ist jederzeit zulässig, die Operation „Verringern“ sollte jedoch mit Vorsicht verwendet werden, da dies dazu führen kann, dass die in Zukunft generierte ID mit der alten Konfiguration übereinstimmt. [Zulassen, dass jeder xxxBitLength-Wert erhöht wird, nachdem das System ausgeführt wird]
? 3. Wenn einer von WorkerIdBitLength oder SeqBitLength reduziert werden muss, muss die Bedingung erfüllt sein: Die Summe der beiden neuen xxxBitLength muss größer sein als die Summe der alten Werte. [ Es wird nicht empfohlen, einen beliebigen BitLength-Wert nach der Ausführung einzuschränken.]
4. Die oben genannten drei Regeln werden in diesem Algorithmus nicht logisch gesteuert. Benutzer sollten Konfigurationsänderungen vornehmen, nachdem sie bestätigt haben, dass die neue Konfiguration den Anforderungen entspricht.
? Der eindeutige ID-Generator basiert auf WorkerId. Wenn Geschäftsdienste eine horizontale und wahllose Replikation erfordern (automatische Erweiterung), erfordert dies die Möglichkeit, automatisch eine global eindeutige WorkerId zu registrieren, bevor eine eindeutige ID generiert wird.
?Dieser Algorithmus stellt eine dynamische Open-Source-Bibliothek (implementiert in der Go-Sprache) bereit, die WorkerId automatisch über Redis in Containerumgebungen wie k8s registrieren kann.
? Die Registrierung von WorkerId über Redis ist nicht die einzige Möglichkeit. Sie können auch einen zentralen Konfigurationsdienst entwickeln. Wenn jeder Endpunktdienst gestartet wird, wird die eindeutige WorkerId über den zentralen Dienst abgerufen.
? Wenn Ihr Dienst nicht automatisch erweitert werden muss, müssen Sie WorkerId natürlich nicht automatisch registrieren, sondern global eindeutige Werte festlegen.
? Es gibt viele Methoden, beispielsweise die Entwicklung eines zentralisierten ID-Generierungsdienstes, der verwendbare IDs für jeden Endpunktdienst (einzeln oder stapelweise) generiert.
Bildlink: https://github.com/yitter/IdGenerator/blob/master/Tools/AutoRegisterWorkerId/regprocess.jpg
Quellcodepfad: /Go/source/regworkerid/reghelper.go
Download-Link: https://github.com/yitter/IdGenerator/releases/download/v1.3.3/workeridgo_lib_v1.3.3.zip
// 注册一个 WorkerId,会先注销所有本机已注册的记录
// address: Redis连接地址,单机模式示例:127.0.0.1:6379,哨兵/集群模式示例:127.0.0.1:26380,127.0.0.1:26381,127.0.0.1:26382
// password: Redis连接密码
// db: Redis指定存储库,示例:1
// sentinelMasterName: Redis 哨兵模式下的服务名称,示例:mymaster,非哨兵模式传入空字符串即可
// minWorkerId: WorkerId 最小值,示例:30
// maxWorkerId: WorkerId 最大值,示例:63
// lifeTimeSeconds: WorkerId缓存时长(秒,3的倍数),推荐值15
extern GoInt32 RegisterOne(char* server, char* password, GoInt32 db, char* sentinelMasterName, GoInt32 minWorkerId, GoInt32 maxWorkerId, GoInt32 lifeTimeSeconds);
// 注销本机已注册的 WorkerId
extern void UnRegister();
Sprache | Github |
---|---|
?C# | Beispiel ansehen |
? Java | Beispiel ansehen |
? Gehen | Beispiel ansehen |
? Rost | Beispiel ansehen |
?Python | Beispiel ansehen |
?C | Beispiel ansehen |
? C (PHP-Erweiterung) | Beispiel ansehen |
? Delphi (Pascal) | Beispiel ansehen |
? JavaScript | Beispiel ansehen |
?Typoskript | Beispiel ansehen |
?V | Beispiel ansehen |
?D | Beispiel ansehen |
Open-Source-Adresse: https://github.com/yitter/IdGenerator
QQ-Gruppe: 646049993