Bei der Auswahl des Datentyps der ID müssen Sie nicht nur den Datenspeichertyp berücksichtigen, sondern auch, wie MySQL diesen Typ berechnet und vergleicht. MySQL speichert beispielsweise ENUM- und SET-Typen intern als Ganzzahlen, vergleicht sie in Zeichenfolgenszenarien jedoch als Zeichenfolgen. Sobald der Datentyp der ID ausgewählt ist, müssen Sie sicherstellen, dass die Datentypen der zugehörigen Datentabellen, die auf die ID verweisen, konsistent und vollständig konsistent sind, einschließlich Eigenschaften wie Länge und ob sie vorzeichenbehaftet sind! Das Mischen unterschiedlicher Datentypen kann zu Leistungsproblemen führen, und selbst wenn keine Leistungsprobleme vorliegen, können implizite Datenkonvertierungen während Vergleichen subtile Fehler verursachen. Werden allerdings im eigentlichen Entwicklungsprozess die unterschiedlichen Datentypen vergessen, kann es plötzlich zu unerwarteten Problemen kommen. Auch bei der Wahl der Länge sollten Sie darauf achten, dass die Feldlänge möglichst klein bleibt und etwas Spielraum für späteres Wachstum bleibt. Wenn es beispielsweise zum Speichern von Provinzen verwendet wird, haben wir nur Dutzende von Werten. Zu diesem Zeitpunkt ist es besser, TINYINT anstelle von INT zu verwenden. Wenn die zugehörige Tabelle auch diese ID speichert, ist der Effizienzunterschied sehr groß. Hier sind einige typische Typen, die für IDs gelten:
Wenn Sie einen UUID-Wert verwenden möchten, sollten Sie das Zeichen "-" entfernen oder ihn mit der Funktion UNHEX in eine 16-Byte-Zahl umwandeln und mit BINARY(16) speichern. Anschließend können Sie die HEX-Funktion verwenden, um es im Hexadezimalformat zu erhalten. Es gibt viele Möglichkeiten, UUIDs zu generieren. Einige sind zufällig verteilt und andere geordnet. Aber selbst die geordneten Methoden weisen keine so gute Leistung auf wie Ganzzahlen. Zusammenfassung der Distributed-ID-LösungenID ist die eindeutige Kennung der Daten. Der traditionelle Ansatz besteht darin, UUID und die Autoinkrement-ID der Datenbank zu verwenden. Heutzutage wird MySQL immer häufiger verwendet, und da es Transaktionsunterstützung erfordert, wird normalerweise die Innodb-Speicher-Engine verwendet. UUID ist zu lang und ungeordnet, daher ist es nicht als Primärschlüssel in Innodb geeignet. Autoinkrement-ID ist geeigneter, aber mit der Geschäftsentwicklung wird die Datenmenge immer größer und die Daten müssen in Tabellen aufgeteilt werden. Nachdem die Tabellen aufgeteilt wurden, werden die Daten in jeder Tabelle in ihrem eigenen Tempo automatisch inkrementiert, und es besteht eine hohe Wahrscheinlichkeit von ID-Konflikten. Derzeit ist ein separater Mechanismus zum Generieren einer eindeutigen ID erforderlich. Die generierte ID kann auch als verteilte ID oder globale ID bezeichnet werden. Lassen Sie uns die Mechanismen zur Generierung verteilter IDs analysieren. Auto-Inkrement-ID der DatenbankDiese Methode basiert auf der Auto-Increment-ID der Datenbank. Sie müssen eine separate Datenbankinstanz verwenden und in dieser Instanz eine separate Tabelle erstellen: Die Tabellenstruktur ist wie folgt: DATENBANK `SEQID` ERSTELLEN; CREATE TABLE SEQID.SEQUENCE_ID ( id bigint(20) unsigned NOT NULL auto_increment, stub char(10) NICHT NULL Standard '', Primärschlüssel (ID), UNIQUE KEY-Stub (Stub) )ENGINE=MyISAM; Mit der folgenden Anweisung können Sie eine Auto-Increment-ID generieren und abrufen. beginnen; ersetzen durch SEQUENCE_ID (Stub) VALUES ('beliebiges Wort'); wählen Sie last_insert_id(); begehen; Das Stub-Feld hat hier keine besondere Bedeutung. Es dient lediglich der Vereinfachung beim Einfügen von Daten. Nur wenn Daten eingefügt werden können, kann eine Auto-Increment-ID generiert werden. Zum Einfügen verwenden wir Ersetzen. Ersetzen prüft zunächst, ob Daten mit demselben Wert wie der angegebene Stub vorhanden sind. Wenn dies der Fall ist, werden sie zuerst gelöscht und dann eingefügt. Wenn dies nicht der Fall ist, werden sie direkt eingefügt. Dieser Mechanismus zum Generieren verteilter IDs erfordert eine separate MySQL-Instanz. Dies ist zwar machbar, reicht jedoch in Bezug auf Leistung und Zuverlässigkeit nicht aus. Jedes Mal, wenn ein Geschäftssystem eine ID benötigt, muss es die Datenbank anfordern, um sie abzurufen, was eine geringe Leistung aufweist. Wenn diese Datenbankinstanz offline geht, sind alle Geschäftssysteme davon betroffen. ; Daher weisen die auf diese Weise erhaltenen Daten einen gewissen Grad an Unzuverlässigkeit auf. Datenbank-MultimastermodusWenn unsere beiden Datenbanken einen Master-Slave-Cluster bilden, kann das Datenbankzuverlässigkeitsproblem unter normalen Umständen gelöst werden. Wenn jedoch die Master-Datenbank ausfällt und die Daten nicht rechtzeitig mit der Slave-Datenbank synchronisiert werden, kommt es zu einer ID-Duplikation. Aus diesem Grund können wir einen Cluster im Multi-Master-Modus ☞ Dual-Master-Modus verwenden, d. h. beide MySQL-Instanzen können unabhängig voneinander Auto-Increment-IDs generieren, was die Effizienz verbessern kann. Wenn jedoch keine anderen Änderungen vorgenommen werden, generieren die beiden MySQL-Instanzen wahrscheinlich dieselbe ID. Sie müssen für jede MySQL-Instanz unterschiedliche Startwerte und Auto-Inkrement-Schritte konfigurieren. Konfiguration der ersten MySQL-Instanz (mysql_01): setze @@auto_increment_offset = 1; -- Startwert setze @@auto_increment_increment = 2; -- Schrittlänge Konfiguration der zweiten MySQL-Instanz (mysql_02): setze @@auto_increment_offset = 2; -- Startwert setze @@auto_increment_increment = 2; -- Schrittlänge Nach der obigen Konfiguration lauten die von den beiden MySQL-Instanzen generierten ID-Sequenzen wie folgt: Für diese Lösung zum Generieren verteilter IDs müssen Sie eine neue Anwendung zum Generieren verteilter IDs hinzufügen, z. B. DistributIdService. Diese Anwendung bietet eine Schnittstelle für Geschäftsanwendungen zum Abrufen von IDs. Wenn eine Geschäftsanwendung eine ID benötigt, fordert sie DistributIdService über RPC an. DistributIdService erhält die ID zufällig von den beiden oben genannten MySQL-Instanzen. Selbst wenn nach der Implementierung dieser Lösung eine der MySQL-Instanzen offline geht, wirkt sich dies nicht auf DistributIdService aus und DistributIdService kann weiterhin ein anderes MySQL zum Generieren von IDs verwenden. Diese Lösung ist jedoch nicht gut skalierbar. Wenn zwei MySQL-Instanzen nicht ausreichen und Sie eine neue MySQL-Instanz hinzufügen müssen, um die Leistung zu verbessern, wird dies problematisch. Wenn Sie jetzt eine neue Instanz mysql_03 hinzufügen möchten, wie gehen Sie vor?
ZahlensegmentmodusDieser Modus kann als Stapelerfassung verstanden werden. Wenn beispielsweise DistributIdService IDs aus der Datenbank abruft und mehrere IDs stapelweise abgerufen und lokal zwischengespeichert werden können, verbessert dies die Effizienz der Geschäftsanwendungen beim Abrufen von IDs erheblich. Beispielsweise erhält DistributIdService jedes Mal, wenn es eine ID aus der Datenbank abruft, ein Zahlensegment, z. B. (1,1000). Dieser Bereich stellt 1000 IDs dar. Wenn die Geschäftsanwendung DistributIdService auffordert, eine ID bereitzustellen, muss DistributIdService die Zahl nur lokal von 1 erhöhen und zurückgeben, ohne jedes Mal die Datenbank anzufordern. Es greift erst dann auf die Datenbank zu, um das nächste Zahlensegment abzurufen, wenn die lokale Zahl auf 1000 erhöht wurde, d. h. wenn das aktuelle Zahlensegment aufgebraucht ist. Daher müssen wir die Datenbanktabelle wie folgt ändern: Tabelle erstellen id_generator ( id int(10) NICHT NULL, current_max_id bigint(20) NOT NULL COMMENT 'Aktuelle maximale ID', increment_step int(10) NOT NULL COMMENT 'Schritt erhöhen', PRIMÄRSCHLÜSSEL (`id`) )ENGINE=InnoDB STANDARD-CHARSET=utf8; In dieser Datenbanktabelle werden der Auto-Increment-Schritt und der aktuelle Maximalwert der Auto-Increment-ID (also der letzte Wert des aktuell verwendeten Nummernsegments) aufgezeichnet. Da die Auto-Increment-Logik in den DistributIdService verschoben wurde, benötigt die Datenbank diese Logik nicht mehr. Diese Lösung ist nicht mehr stark von der Datenbank abhängig. Selbst wenn die Datenbank nicht verfügbar ist, kann DistributIdService sie für einen bestimmten Zeitraum weiterhin unterstützen. Wenn der DistributIdService jedoch neu gestartet wird, geht ein ID-Segment verloren, was zu ID-Lücken führt. Um die hohe Verfügbarkeit von DistributIdService zu verbessern, ist ein Cluster erforderlich. Wenn ein Unternehmen den DistributIdService-Cluster anfordert, um eine ID abzurufen, wählt es nach dem Zufallsprinzip einen DistributIdService-Knoten aus, um diese abzurufen. Für jeden DistributIdService-Knoten ist die Datenbank mit derselben Datenbank verbunden, sodass mehrere DistributIdService-Knoten die Datenbank gleichzeitig anfordern können, um das Nummernsegment abzurufen. In diesem Fall ist zur Steuerung eine optimistische Sperre erforderlich. Beispielsweise wird der Datenbanktabelle ein Versionsfeld hinzugefügt. Beim Abrufen des Nummernsegments wird das folgende SQL verwendet: Aktualisiere ID_Generator, setze current_max_id=#{newMaxId}, Version=Version+1, wobei Version = #{Version} Da newMaxId im DistributIdService basierend auf oldMaxId + Schrittgröße berechnet wird, bedeutet dies, dass das Zahlensegment erfolgreich abgerufen wurde, solange das obige Update erfolgreich ist. Um eine hohe Verfügbarkeit der Datenbankschicht zu gewährleisten, muss die Datenbank im Multi-Master-Modus bereitgestellt werden. Für jede Datenbank muss sichergestellt werden, dass die generierten Zahlensegmente nicht wiederholt werden. Dazu muss die ursprüngliche Idee verwendet und der Startwert und die Schrittweite zur Datenbanktabelle hinzugefügt werden. Wenn beispielsweise zwei MySQL-Server vorhanden sind, gilt Folgendes: Den spezifischen Implementierungscode finden Sie unter: tinyid Snowflake-Algorithmus Die drei Modi Datenbank-Selbstinkrement-ID-Modus, Datenbank-Multimastermodus und Zahlensegmentmodus basieren alle auf der Idee der Selbstinkrementierung. Die Idee des Schneeflockenalgorithmus kann unten kurz verstanden werden. Die Kernidee besteht darin, dass die verteilte ID eine feste lange Zahl ist. Eine lange Zahl belegt 8 Bytes, also 64 Bits. Die Zuordnung der Bits im ursprünglichen Snowflake-Algorithmus ist wie folgt:
Gemäß der Logik dieses Algorithmus müssen wir diesen Algorithmus nur in der Java-Sprache implementieren und in eine Tool-Methode kapseln. Dann kann jede Geschäftsanwendung diese Tool-Methode direkt verwenden, um die verteilte ID zu erhalten. Wir müssen nur sicherstellen, dass jede Geschäftsanwendung ihre eigene Arbeitsmaschinen-ID hat, ohne eine separate Anwendung erstellen zu müssen, um die verteilte ID zu erhalten. Es ist außerdem nicht auf eine Datenbank angewiesen. Spezifische Codeimplementierung Paket com.yeming.tinyid.application; importiere static java.lang.System.*; /** * @Autor yeming.gao * @Description: Implementierung des Snowflake-Algorithmus* <p> * Der SnowFlake-Algorithmus wird zum Generieren von 64-Bit-IDs verwendet, die in langen Ganzzahlen gespeichert und zum Generieren eindeutiger IDs in verteilten Systemen verwendet werden können. * Und die generierten IDs haben eine ungefähre Reihenfolge. In dieser Implementierung kann die generierte 64-Bit-ID in fünf Teile aufgeteilt werden: * 0 - 41-Bit-Zeitstempel - 5-Bit-Rechenzentrums-ID - 5-Bit-Maschinen-ID - 12-Bit-Seriennummer * @date 2020/07/28 16:15 */ öffentliche Klasse SnowFlake { /** * Startzeitstempel */ privates statisches endgültiges langes START_STMP = 1480166465631L; /** * Anzahl der Ziffern der Maschinen-ID */ privates statisches endgültiges langes MACHINE_BIT = 5; /** * Anzahl der vom Rechenzentrum belegten Bits */ privat statisch endgültig lang DATACENTER_BIT = 5; /** * Anzahl der Ziffern der Seriennummer */ privates statisches endgültiges langes SEQUENCE_BIT = 12; /** * Maximalwert der Maschinen-ID*/ privates statisches endgültiges langes MAX_MACHINE_NUM = ~ (-1L << MACHINE_BIT); /** * Maximalwert des Rechenzentrums */ privates statisches endgültiges langes MAX_DATACENTER_NUM = ~(-1L << DATACENTER_BIT); /** * Maximaler Seriennummernwert */ privates statisches endgültiges langes MAX_SEQUENCE = ~ (-1L << SEQUENCE_BIT); /** * Die Verschiebung jedes Teils nach links*/ privates statisches endgültiges langes MACHINE_LEFT = SEQENCE_BIT; privat statisch endgültig lang DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT; privat statisch endgültig lang TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT; private long datacenterId; //Rechenzentrumprivate long machineId; //Maschinen-IDprivate long sequence = 0L; //Seriennummerprivate long lastStmp = -1L; //Letzter Zeitstempelprivate SnowFlake(long datacenterId, long machineId) { wenn (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) { throw new IllegalArgumentException("datacenterId darf nicht größer als MAX_DATACENTER_NUM oder kleiner als 0 sein"); } wenn (Maschinen-ID > MAX_MASCHINENANZAHL || Maschinen-ID < 0) { throw new IllegalArgumentException("machineId darf nicht größer als MAX_MACHINE_NUM oder kleiner als 0 sein"); } this.datacenterId = Datencenter-ID; this.machineId = Maschinen-Id; } /** * Generieren Sie die nächste ID * * @return lang */ private synchronisierte lange nextId() { lange currStmp = System.currentTimeMillis(); wenn (aktuellerStmp < letzterStmp) { throw new RuntimeException("Uhr wurde zurückgestellt. ID-Generierung wird abgelehnt"); } wenn (aktuellerStmp == letzterStmp) { //In der gleichen Millisekunde erhöht sich die Sequenznummer automatisch sequence = (sequence + 1) & MAX_SEQUENCE; //Die Anzahl der Sequenzen in derselben Millisekunde hat das Maximum erreicht if (sequence == 0L) { currStmp = getNextMill(); } } anders { //In verschiedenen Millisekunden wird die Sequenznummer auf 0 gesetzt Sequenz = 0L; } letzterStmp = aktuellerStmp; return (currStmp - START_STMP) << TIMESTMP_LEFT //Zeitstempelteil | datacenterId << DATACENTER_LEFT //Rechenzentrumteil | machineId << MACHINE_LEFT //Maschinen-ID-Teil | sequence; //Seriennummernteil} private long getNextMill() { lange Mühle = System.currentTimeMillis(); während (Mühle <= letzterStmp) { Mühle = System.currentTimeMillis(); } Rücklaufmühle; } öffentliche statische void main(String[] args) { Schneeflocke Schneeflocke = neue Schneeflocke (2, 3); // Maximalwert der Rechenzentrumskennung long maxDatacenterNum = ~(-1L << DATACENTER_BIT); //Maximaler Wert der Maschinenkennung long maxMachineNum = ~(-1L << MACHINE_BIT); // Maximalwert der Sequenznummer long maxSequence = ~(-1L << SEQUENCE_BIT); out.println("Maximaler Wert der Rechenzentrums-ID: " + maxDatacenterNum + "; Maximaler Wert der Maschinen-ID: " + maxMachineNum + "; Maximaler Wert der Sequenznummer: " + maxSequence); für (int i = 0; i < (1 << 12); i++) { out.println(snowFlake.nextId()); } } } Der Snowflake-Algorithmus kann sich beziehen auf:
Oben finden Sie Einzelheiten zur Auswahl des geeigneten Datentyps für die MySQL-ID. Weitere Informationen zur Auswahl des geeigneten Datentyps für die MySQL-ID finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM! Das könnte Sie auch interessieren:
|
<<: 3 verschiedene Möglichkeiten zum Löschen der Optionsoptionen im Auswahltag
>>: Implementierungsschritte für die Docker-Bereitstellung von Springboot- und Vue-Projekten
Da der Standard-AB nur Stresstests für eine einze...
Nginx Rewrite-Nutzungsszenarien 1. Sprung der URL...
Dieser Artikel zeichnet einige wichtige Einstellu...
1. Dynamische Abfrageregeln Die dynamischen Abfra...
In MySQL kann das Problem der Groß- und Kleinschr...
Dieser Artikel installiert die Google-Eingabemeth...
Inhaltsverzeichnis 1. Vertikales (längsseitiges) ...
Vorwort JavaScript unterscheidet sich von anderen...
Inhaltsverzeichnis 1. Was ist eine Vorlagenzeiche...
1. Reverse-Proxy-Beispiel 1 1. Erzielen Sie den E...
Verwenden Sie das RPM-Installationspaket, um MySQ...
Nach drei Tagen voller Schwierigkeiten habe ich d...
ins und del wurden in HTML 4.0 eingeführt, um Auto...
Berechtigungen und Datenbankdesign Benutzerverwal...
Inhaltsverzeichnis 1. Bilder 1. Was ist ein Spieg...