Bei der Entwicklung eines Serversystems, um sich an große und gleichzeitige Datenanfragen anzupassen, müssen wir die Daten häufig asynchron speichern, insbesondere bei der Arbeit in einem verteilten System. Zu diesem Zeitpunkt können wir es kaum erwarten, dass die Insertion -Datenbank die automatische ID zurückgibt. Stattdessen müssen wir eine globale eindeutige ID generieren, bevor wir die Datenbank mithilfe der globalen eindeutigen ID einfügen. Auf dem Spielserver kann die globale eindeutige ID für zukünftige Serverkombinationen verwendet werden und es wird keine Schlüsselkonflikte geben. In Zukunft kann im Falle eines Geschäftswachstums die Datenbank und die Split -Tabelle implementiert werden. Beispielsweise müssen die Elemente eines Benutzers in denselben Shard platziert werden, und dieser Shard kann basierend auf dem Bereich der Benutzer -ID ermittelt werden, z. B. eine Benutzer -ID mit einer Benutzer -ID von mehr als 1000 und weniger als 100000 in einem Shard. Derzeit werden die folgenden häufig verwendet:
1. Javas eigener Uuid.
UUid.randomuuid (). ToString () kann lokal über das Serviceprogramm generiert werden, und die Generierung von ID hängt nicht von der Implementierung der Datenbank ab.
Vorteile:
Erstellen Sie die ID lokal und benötigen keine Remote -Anrufe.
Die Welt ist die einzige, die sich nicht wiederholt.
Die horizontale Expansionsfähigkeit ist sehr gut.
Nachteile:
Die ID verfügt über 128 Bit, was einen großen Raum einnimmt und als String -Typ gespeichert werden muss, und die Indexierungseffizienz ist extrem niedrig.
Die generierte ID enthält keinen Zeitstempel, und der Trend kann nicht garantiert werden. Es ist schwierig, sich bei der Aufteilung von Datenbankdatenbanken zu verlassen.
2. REDIS-basierte Inkret-Methode
Redis selbst wird Single-Threaded und inkret sorgt für einen atomisch inkrementierten Betrieb. Es unterstützt auch die Einstellung einer inkrementellen Schrittgröße.
Vorteile:
Es ist einfach zu bereitstellen und einfach zu bedienen. Sie müssen nur eine Redis -API anrufen.
Mehrere Server können einen Redis -Service teilen, um die Entwicklungszeit von gemeinsamen Daten zu verkürzen.
Redis kann in Clustern eingesetzt werden, um das Problem eines einzelnen Fehlerpunkts zu lösen.
Nachteile:
Wenn das System zu groß ist, verursacht mehrere Dienste, die gleichzeitig auf Redis sind, Leistungs Engpässe verursachen.
3. Lösung vom Flackern
Diese Lösung basiert auf der automatischen Inkrement-ID der Datenbank, die eine separate Datenbank speziell zum Generieren von IDs verwendet. Sie können die Details online finden. Ich persönlich denke, es ist ziemlich problematisch zu verwenden, und es wird nicht empfohlen, es zu verwenden.
4. Twitter Snowflake
Snowflake ist ein verteilter ID -Generierungalgorithmus, der Open Source auf Twitter ist. Die Kernidee besteht darin, eine Long-ID zu generieren, wobei 41bit als Anzahl der Millisekunden, 10bit als Maschinennummer und 12-Bit als Seriennummer innerhalb von Millisekunden verwendet wird. Dieser Algorithmus kann theoretisch bis zu 1.000*(2^12) IDs pro Sekunde pro Maschine erzeugen, was etwa 400 W beträgt und die Bedürfnisse des Geschäfts vollständig erfüllen kann.
Nach der Idee des Snowflake -Algorithmus können wir unsere eigene globale eindeutige ID basierend auf unseren Geschäftsszenarien generieren. Da die Länge des langen Typs in Java 64bit beträgt, muss die von uns entworfene ID bei 64Bit kontrolliert werden.
Vorteile: hohe Leistung, geringe Latenz; unabhängige Anwendung; ordentlich nach Zeit.
Nachteile: Unabhängige Entwicklung und Bereitstellung sind erforderlich.
Beispielsweise enthält die von uns entworfene ID die folgenden Informationen:
| 41 Bit: Timestamp | 3 Bits: Bereich | 10 Bit: Maschinennummer | 10 Bit: Seriennummer |
Java -Code, der eine eindeutige ID generiert:
/*** Benutzerdefinierte ID -Generator* ID -Generierungsregeln: ID bis zu 64 Bits ** | 41 Bit: TimeStamp (MS) | 3 Bit: Bereich (Computerraum) | 10 Bit: Maschinennummer | 10 Bits: Seriennummer |*/public class gameUuid {// Referenzzeit private long Twepoch = 1288834974657L; // Thu, 04. November 2010 01:42:54 GMT // Region Flagd -Ziffern Private endgültige statische lange RegionIDIdbits = 3L; // Maschinenidentifikationsstellen private endgültige statische lange Arbeiter -Ohrfits = 10L; // Seriennummer Ziffern privates endgültiges statisches Langsequenzbits = 10L; // Maximaler Wert der Region. Maximaler Wert von Maschinen ID Private endgültige statische lange maxworkerid = -1l ^ (-1l << WorkerIdbits); // Maximaler Wert der Seriennummer ID Private endgültige statische lange Sequencemask = -1l ^ (-1l << SequencyBits); // Die Maschinen -ID ist 10 Bits auf der linken privaten endgültigen statischen Langzeit -Langzeit -Langzeit -Länge von 20 bits. RegionIdShift = SequenceBits + WorkerIdbits; // Die Zeit wird von 23 Bits verlagert. private static long lastTimestamp = -1l; private lange Sequenz = 0L; private lande lange ArbeiterID; private endgültige Lange RegionID; public GameUuid (lange Arbeiter, lange RegionID) {// Wenn außerhalb der Reichweite eine Ausnahme ausgelöst wird (WorkerID> Maxworkerid || WorkerID <0) {Neue IllegalArgumentException ("Arbeiter -ID kann nicht größer als %d oder weniger als 0") sein (RegionID> maxregionaler illyal. als 0 ");} this.workerId = WorkerID; this.regionId = RegionId;} public GameUuId (Long WorkerID) {// Wenn außerhalb von Reichweite geworfen wird, wenn (WorkerID> maxworkerId || WorkerID <0) {Neue IllegalArgumentException ("Arbeiter -ID kann nicht größer sein als %d oder weniger als 0");} this. 0);}/*** Der tatsächliche Code, der von @param ispadding* @param busid* @return*/private synchronisierte long NextID (boolesche ISspadding, Long busid) {Long TimeStamp = TimeGen (); Long PaddingNum = RegionId; if (ispadding) {padding = bussid;} if (TISTESTAMP) {TOCKSID; {TOCKSID;} if (TISTESTAMP) {{{TOCKSID;} if (TISTESTAMP) {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{coUnd. rückwärts. Nur 10bit, es wird mit Sequencemask kombiniert und die Hochbit-Sequenz = (Sequenz + 1) und Sequencemask; // beurteilen, ob sie überläuft, dh es überschreitet 1024 in jeder Millisekunde. Wenn es 1024 ist, wird es mit Sequencemask kombiniert, und die Sequenz ist gleich 0if (Sequence == 0) {// Spin wartet bis zum nächsten Millisekunden -Zeitstempel = TailNextMillis (lastTimestamp);}} sonst {// Wenn die Sequenz von der letzten Generation von der Sequenz abweist, startet die Sequenz, die in der nächsten Millisekorte startet. // Um sicherzustellen, dass die Mantissa zufällig ist, setzen Sie eine Zufallszahl in der letzten Bitsequenz = new Securerandom (). NextInt (10);} lastTimestamp = timestamp; return ((TimeStamp - Twepoch) << TimestampleftShift) | (paddingnum << RegionIdShift) | (WorkerID << WorkerIdShift) | Sequenz;} // verhindern, dass die Erzeugungszeit kleiner als die vorherige Zeit ist (aufgrund von Problemen wie NTP -Rückruf), und den inkrementellen Trend beibehalten. timeGen () {return system.currentTimemillis ();}}Einige Dinge zu beachten, wenn Sie benutzerdefinierte Methoden verwenden:
Um den Wachstumstrend aufrechtzuerhalten, muss die Zeit einiger Server frühzeitig und einiger Server spät eingestellt werden. Daher muss die Zeit aller Server kontrolliert werden und die Zeit, in der der NTP -Zeitserver zum Server zurückruft, wird vermieden. Beim Überqueren von Millisekunden erreicht die Seriennummer immer 0, was mehr IDs mit der Seriennummer 0 ergibt, was nach dem Modulen zu ungleichmäßigen IDs führt, sodass die Seriennummer nicht jedes Mal zu 0 gehört, sondern eine Zufallszahl von 0 bis 9.
Wir können die oben genannten Methoden entsprechend unseren Bedürfnissen auswählen. In der Entwicklung von Game Server können Sie nach Ihrem eigenen Spieltyp wie Mobilfunkspielen auswählen und die einfache Redis -Methode verwenden, die einfach und nicht einfach zu machen ist. Da die Anzahl der neuen IDs, die von einzelnen Servern in dieser Art von Spiel erstellt wurden, nicht zu groß ist, kann dies den Anforderungen vollständig erfüllen. Für große Weltspielserver sind sie hauptsächlich verteilt, sodass Sie Snowflake verwenden können. Der obige Schneeflockencode ist nur ein Beispiel und muss entsprechend Ihren Anforderungen angepasst werden. Daher gibt es zusätzliches Entwicklungsvolumen, und Sie sollten auf die oben genannten Vorsichtsmaßnahmen achten.
Das obige ist eine Zusammenfassung der Methoden zur Verwendung von Java -Code, um den Spielserver zu implementieren, um eine globale eindeutige ID basierend auf Java -Code zu generieren. Ich hoffe, es wird für alle hilfreich sein. Wenn Sie Fragen haben, hinterlassen Sie mir bitte eine Nachricht und der Editor wird allen rechtzeitig antworten. Vielen Dank für Ihre Unterstützung auf der Wulin.com -Website!