Prinzip und Implementierung der parallelen Replikation von MySQL5.7

Prinzip und Implementierung der parallelen Replikation von MySQL5.7

Jeder, der ein wenig über Datenoperationen und -wartung weiß, weiß, dass MySQL 5.5 und früher einen einzelnen SQL-Thread für die Wiedergabe verwenden. Wenn der Master QPS etwas höher ist, tritt eine Verzögerung auf. 5.6 ist ein bibliotheksbasierter paralleler Wiedergabemechanismus. Nur wenn mehrere Bibliotheken vorhanden sind, kann die Replikation einen Vorteil haben. 5.7 ist eine gruppenbasierte parallele Wiedergabe. Transaktionen in derselben Gruppe können parallel wiedergegeben werden, um das Verzögerungsproblem zu lösen.

MySQL 5.7 - Ära der parallelen Replikation

Wie wir alle wissen, ist die Verzögerung der MySQL-Replikation eines der Probleme, die kritisiert wurden. In den beiden vorherigen Blogs von Inside Jun (1, 2) wurde jedoch erwähnt, dass die Version MySQL 5.7 bereits eine „echte“ parallele Replikationsfunktion unterstützt, die offiziell als Enhanced Multi-Threaded Slave (kurz MTS) bezeichnet wird. Daher wurde das Problem der Replikationsverzögerung erheblich verbessert. Sogar in der NetEase-E-Commerce-Anwendung, mit der Inside Jun arbeitet, wurde das Problem der Verzögerung von mehreren Stunden vollständig behoben. Ich habe jedoch festgestellt, dass viele Freunde dieses „großartige“ Feature, das es wert ist, in die Geschichte einzugehen, immer noch nicht verstehen, deshalb habe ich beschlossen, es mit Ihnen zu teilen. Kurz gesagt: Nach Version 5.7 wird das Problem der Replikationsverzögerung nicht mehr auftreten.

MySQL 5.6 Parallele Replikationsarchitektur

Zwar unterstützt MySQL in der Version 5.6 auch die sogenannte parallele Replikation, allerdings ist die Parallelität dort ausschließlich schemabasiert, also bibliotheksbasiert. Wenn in der MySQL-Datenbankinstanz des Benutzers mehrere Schemas vorhanden sind, kann dies die Geschwindigkeit der Slave-Replikation tatsächlich erheblich steigern. Die Architektur der parallelen Replikation von MySQL 5.6 ist wie folgt:

Der rot umrahmte Teil in der obigen Abbildung ist der Schlüssel zur parallelen Replikation. Vor MySQL 5.6 gab es zwei Threads auf dem Slave-Server: den I/O-Thread und den SQL-Thread. Der E/A-Thread ist für den Empfang von Binärprotokollen (oder genauer gesagt von Binärprotokollereignissen) verantwortlich und der SQL-Thread gibt Binärprotokolle wieder. Wenn die parallele Replikationsfunktion in MySQL Version 5.6 aktiviert ist, wird der SQL-Thread zum Koordinator-Thread, der hauptsächlich für die folgenden zwei Teile verantwortlich ist:

  • Wenn festgestellt wird, dass eine parallele Ausführung möglich ist, wird das Binärprotokoll der Transaktion zur Ausführung im Arbeitsthread ausgewählt.
  • Wenn festgestellt wird, dass eine parallele Ausführung nicht möglich ist (z. B. weil es sich bei dem Vorgang um einen DDL- oder schemaübergreifenden Transaktionsvorgang handelt), warten Sie, bis alle Arbeitsthreads abgeschlossen sind, bevor Sie das aktuelle Protokoll ausführen.

Dies bedeutet, dass der Koordinator-Thread nicht nur Protokolle an den Worker-Thread sendet, sondern auch selbst Protokolle wiedergeben kann, sondern dass alle Operationen, die parallelisiert werden können, vom Worker-Thread ausgeführt werden. Der Koordinator-Thread und der Worker sind typische Produzenten- und Konsumentenmodelle.

Der obige Mechanismus implementiert eine schemabasierte parallele Replikation, es gibt jedoch zwei Probleme. Erstens ist die Absturzsicherungsfunktion schwierig zu implementieren, da später ausgeführte Transaktionen aufgrund der parallelen Replikation möglicherweise zuerst abgeschlossen werden. Wenn dann ein Absturz auftritt, ist die Verarbeitungslogik dieses Teils relativ kompliziert. Aus Sicht des Codes führt 5.6 das Low-Water-Mark-Tag ein, um dieses Problem zu lösen. Aus gestalterischer Sicht hofft es, dieses Problem mithilfe der Idempotenz des Protokolls zu lösen. Die binäre Protokollwiedergabe von 5.6 kann jedoch keine Idempotenz erreichen. Ein weiteres kritisches Problem ist, dass der parallele Replikationseffekt dieses Designs nicht sehr hoch ist. Wenn die Benutzerinstanz nur über eine Bibliothek verfügt, kann keine parallele Wiedergabe erreicht werden und die Leistung kann sogar schlechter sein als bei der ursprünglichen Single-Thread-Version. Eine einzelne Datenbank mit mehreren Tabellen ist ein häufigeres Szenario als mehrere Datenbanken mit mehreren Tabellen.

MySQL 5.7 Parallele Replikation basierend auf Gruppen-Commit

MySQL 5.7 kann als echte parallele Replikation bezeichnet werden. Der Hauptgrund dafür ist, dass die Wiedergabe des Slave-Servers mit der des Hosts übereinstimmt, d. h. der Slave-Server gibt dieselbe parallele Ausführung wieder wie der Master-Server.

Die Idee der parallelen Replikation in MySQL 5.7 ist einfach und leicht zu verstehen. Kurz gesagt: Alle von einer Gruppe übermittelten Transaktionen können parallel wiederholt werden, da diese Transaktionen in die Vorbereitungsphase der Transaktion eingetreten sind, was bedeutet, dass es keinen Konflikt zwischen den Transaktionen gibt (sonst wäre eine Übermittlung unmöglich).

Um mit der bibliotheksbasierten parallelen Replikation von MySQL 5.6 kompatibel zu sein, führt 5.7 eine neue Variable ein, den Slave-Parallel-Typ, deren konfigurierbare Werte sind:

  • DATABASE: Standardwert, bibliotheksbasierte parallele Replikation
  • LOGICAL_CLOCK: Parallele Replikation basierend auf Gruppen-Commit

GTID-Unterstützung für parallele Replikation

Ein weiteres Problem besteht darin, herauszufinden, ob eine Transaktion zu einer Gruppe gehört, da das ursprüngliche MySQL derartige Informationen nicht bereitstellt. In MySQL 5.7 besteht das Konzept darin, Gruppen-Commit-Informationen in GTID zu speichern. Was passiert, wenn der Benutzer die GTID-Funktion nicht aktiviert, d. h. den Parameter gtid_mode auf OFF setzt? Aus diesem Grund wurde in MySQL 5.7 ein Binärprotokoll-Ereignistyp namens Anonymous_Gtid eingeführt, beispielsweise:

mysql> BINLOG-EREIGNISSE in „mysql-bin.000006“ ANZEIGEN;
 +------------------+-----+----------------+-------------+----------+-------------------------------------------+
 | Logname | Pos | Ereignistyp | Server-ID | End_log_pos | Info |
 +------------------+-----+----------------+-------------+----------+-------------------------------------------+
 | mysql-bin.000006 | 4 | Format_desc | 88 | 123 | Serverversion: 5.7.7-rc-debug-log, Binlogversion: 4 |
 | mysql-bin.000006 | 123 | Vorherige_gtids | 88 | 194 | f11232f7-ff07-11e4-8fbb-00ff55e152c6:1-2 |
 | mysql-bin.000006 | 194 | Anonymous_Gtid | 88 | 259 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
 | mysql-bin.000006 | 259 | Abfrage | 88 | 330 | BEGIN |
 | mysql-bin.000006 | 330 | Table_map | 88 | 373 | table_id: 108 (aaa.t) |
 | mysql-bin.000006 | 373 | Zeilen schreiben | 88 | 413 | table_id: 108 Flags: STMT_END_F |
 .....

Dies bedeutet, dass in MySQL 5.7, auch wenn GTID nicht aktiviert ist, vor dem Start jeder Transaktion ein Anonymous_Gtid vorhanden ist und dieses GTID Informationen zum Gruppen-Commit enthält.

LOGISCHE_UHR

Über die oben stehenden SHOW BINLOG EVENTS konnten wir jedoch keine Informationen zur Gruppenübermittlung finden. Über das Tool mysqlbinlog können Benutzer jedoch die von der Gruppe übermittelten internen Informationen finden:

# mysqlbinlog mysql-bin.0000006 | grep last_committed
#150520 14:23:11 Server-ID 88 End-Log-Position 259 CRC32 0x4ead9ad6 GTID last_committed=0 Sequenznummer=1
#150520 14:23:11 Server-ID 88 End-Log-Pos 1483 CRC32 0xdf94bc85 GTID last_committed=0 Sequenznummer=2
#150520 14:23:11 Server-ID 88 End-Log-Pos 2708 CRC32 0x0914697b GTID last_committed=0 Sequenznummer=3
#150520 14:23:11 Server-ID 88 End-Log-Pos 3934 CRC32 0xd9cb4a43 GTID last_committed=0 Sequenznummer=4
#150520 14:23:11 Server-ID 88 End-Log-Pos 5159 CRC32 0x06a6f531 GTID last_committed=0 Sequenznummer=5
#150520 14:23:11 Server-ID 88 End-Log-Pos 6386 CRC32 0xd6cae930 GTID last_committed=0 Sequenznummer=6
#150520 14:23:11 Server-ID 88 End-Log-Pos 7610 CRC32 0xa1ea531c GTID last_committed=6 Sequenznummer=7
...

Es lässt sich feststellen, dass im Vergleich zum ursprünglichen Binärprotokollinhalt mehr last_committed und sequence_number vorhanden sind. Last_committed gibt die Nummer der letzten Transaktion an, die zum Zeitpunkt des Commits der Transaktion festgeschrieben wurde. Wenn Transaktionen dasselbe last_committed aufweisen, bedeutet dies, dass sich diese Transaktionen in einer Gruppe befinden und parallel wiedergegeben werden können. Beispielsweise gibt es 6 Transaktionen, bei denen „last_committed“ 0 ist. Dies bedeutet, dass während des Gruppen-Commits 6 Transaktionen festgeschrieben wurden und diese 6 Transaktionen parallel auf dem Slave wiedergegeben werden können.

Die oben erwähnten last_committed und sequence_number stellen die sogenannte LOGICAL_CLOCK dar. Schauen wir uns zunächst die Definition von LOGICAL_CLOCK im Quellcode an:

Klasse Logical_clock
 {
 Privat:
 int64-Status;
 /*
 Der Offset wird vom tatsächlichen „absoluten Zeitwert“ abgezogen bei
 Protokollierung eines Replikationsereignisses. Das heißt, das Ereignis enthält logische
 Zeitstempel im "relativen" Format. Sie sind nur dann sinnvoll, wenn
 der Kontext des aktuellen Binlogs.
 Das Mitglied wird pro binärer Protokollrotation aktualisiert (inkrementiert).
 */
 int64-Offset;
 ......

Der Status ist ein automatisch inkrementierender Wert. Der Offset wird bei jeder Rotation des Binärprotokolls aktualisiert und der Statuswert zum Zeitpunkt der Rotation wird aufgezeichnet. Tatsächlich zeichnen Status und Offset den globalen Zählwert auf, während das Binärprotokoll nur den relativen Wert der aktuellen Datei speichert. Die Szenarien für die Verwendung von LOGICAL_CLOCK sind wie folgt:

Klasse MYSQL_BIN_LOG: öffentliches TC_LOG
 {
 ...
 öffentlich:
 /* Zeitstempel der festgeschriebenen Transaktionen */
 Logische Uhr, max. festgeschriebene Transaktion;
 /* Zeitstempel der „Vorbereiteten“ Transaktionen */
 Logischer_Takt-Transaktionszähler;
 ...

Sie können sehen, dass in der Klasse MYSQL_BIN_LOG zwei Logical_clock-Variablen definiert sind:

  • max_committed_transaction: zeichnet die logische Uhr des letzten Gruppen-Commits auf, was last_committed im obigen mysqlbinlog darstellt
  • transaction_counter: zeichnet die logcial_clock jeder Transaktion in der aktuellen Gruppenübermittlung auf und stellt die sequence_number im obigen mysqlbinlog dar

Paralleler Replikationstest

Die folgende Abbildung zeigt die QPS des Slave-Servers, nachdem MTS aktiviert wurde. Das Testtool ist der Single-Table-Full-Update-Test von Sysbench. Die Testergebnisse zeigen, dass die Leistung unter 16 Threads am besten ist und die QPS des Slaves mehr als 25.000 erreichen kann. Eine weitere Erhöhung der Anzahl parallel ausgeführter Threads auf 32 bringt keine größere Verbesserung. Die QPS der ursprünglichen Single-Thread-Wiedergabe beträgt nur etwa 4000, was die Leistungsverbesserung durch MySQL 5.7 MTS zeigt. Da der Test jedoch auf einer einzelnen Tabelle erfolgt, ist der MTS-Mechanismus von MySQL 5.6 völlig machtlos.

MySQL

MySQL 5.7 Parallele Replikation

Konfiguration und Feinabstimmung paralleler Replikationen

Master-Info-Repository

Achten Sie nach dem Aktivieren der MTS-Funktion darauf, den Parameter master_info_repostitory auf TABLE zu setzen. Dadurch kann die Leistung um 50 % bis 80 % gesteigert werden. Dies liegt daran, dass bei aktivierter paralleler Replikation die Aktualisierung der Datei meta-master.info erheblich zunimmt und auch der Wettbewerb um Ressourcen zunimmt. In früheren Versionen von InnoSQL wurden Parameter hinzugefügt, um die Häufigkeit der Aktualisierung der Datei master.info zu steuern oder sogar die Aktualisierung zu verhindern. Da das Aktualisieren dieser Datei nicht erforderlich ist, ist eine Wiederherstellung auf Grundlage der Datei „master-info.log“ selbst unzuverlässig. In MySQL 5.7 empfiehlt Insider, master_info_repository auf TABLE zu setzen, um diesen Overhead zu reduzieren.

Slave_Parallel_Worker

Wenn slave_parallel_workers auf 0 gesetzt ist, degeneriert MySQL 5.7 zur ursprünglichen Single-Thread-Replikation. Wenn slave_parallel_workers jedoch auf 1 gesetzt ist, wird die SQL-Thread-Funktion in den Koordinator-Thread umgewandelt, es gibt jedoch nur einen Worker-Thread für die Wiedergabe, der ebenfalls eine Single-Thread-Replikation ist. Es gibt jedoch einige Unterschiede zwischen den beiden Leistungen. Da es eine weitere Weiterleitung des Koordinator-Threads gibt, ist die Leistung von slave_parallel_workers=1 schlechter als die von 0. Im Test von Inside gibt es immer noch einen Leistungsabfall von 20 %, wie in der folgenden Abbildung dargestellt:

MySQL
​​​​​​MySQL 5.7 Parallele Replikation​​​​​​

Dies führt zu einem weiteren Problem. Wenn die Last auf dem Host nicht groß ist, ist die Effizienz der Gruppenübermittlung gering. Es ist sehr wahrscheinlich, dass in jeder Gruppe nur eine Transaktion übermittelt wird. Bei der Wiedergabe auf dem Slave ist die Leistung trotz aktivierter paralleler Replikation schlechter als die ursprüngliche Single-Thread-Leistung, d. h. die Verzögerung nimmt zu. Schlaue Freunde, habt ihr schon einmal daran gedacht, dies zu optimieren?

Verbesserte Multithread-Slave-Konfiguration

Abgesehen davon ist es eigentlich ganz einfach, den erweiterten Multithread-Slave zu aktivieren. Befolgen Sie einfach die folgenden Einstellungen:

# Sklave
Slave-Parallel-Typ = LOGISCHE_UHR
Sklaven-Parallelarbeiter = 16
master_info_repository=TABELLE
relay_log_info_repository=TABELLE
relay_log_recovery=EIN

Parallele Replikationsüberwachung

Die Replikationsüberwachung kann weiterhin mit SHOW SLAVE STATUS\G durchgeführt werden, aber MySQL 5.7 fügt unter der performance_schema-Architektur die folgenden Metadatentabellen hinzu, die es Benutzern ermöglichen, die Replikation detaillierter zu überwachen:

mysql> Tabellen wie „Replikation%“ anzeigen;
 +---------------------------------------------+
 | Tabellen_im_Performanceschema (Replikation %) |
 +---------------------------------------------+
 | Replikationsapplier-Konfiguration |
 | Replikationsapplierstatus |
 | Replikationsapplierstatus nach Koordinator |
 | Replikationsapplierstatus nach Arbeiter |
 | Replikationsverbindungskonfiguration |
 | Replikationsverbindungsstatus |
 | Statistiken der Replikationsgruppenmitglieder |
 | Mitglieder_der_Replikationsgruppe |
 +---------------------------------------------+
 8 Zeilen im Satz (0,00 Sek.)

Zusammenfassen

Der in MySQL 5.7 eingeführte Enhanced Multi-Threaded Slave löst das Replikationsverzögerungsproblem, das MySQL seit Jahrzehnten plagt. Dies erinnert einige unwissende PostgreSQL-Benutzer erneut daran, nicht bei ihren bisherigen Eindrücken von MySQL zu bleiben. Die physische Replikation hat nicht unbedingt einen Vorteil gegenüber der logischen Replikation. Das MTS von MySQL 5.7 kann das Verzögerungsproblem vollständig lösen.

Referenz:

- http://www.ttlsa.com/mysql/mysql-5-7-enhanced-multi-thread-salve/

- http://moguhu.com/article/detail?articleId=129

- https://www.codercto.com/a/63073.html

- https://dev.mysql.com/doc/refman/5.7/en/replication-options-replica.html#sysvar_slave_preserve_commit_order

Dies ist das Ende dieses Artikels über das Prinzip und die Implementierung der parallelen Replikation von MySQL 5.7. Weitere relevante Inhalte zur parallelen Replikation von MySQL 5.7 finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird!

Das könnte Sie auch interessieren:
  • Detaillierte Erläuterung der MySQL Master-Slave-Replikation und der Lese-/Schreibtrennung
  • Gängige Reparaturmethoden für die Trennung der MySQL Master-Slave-Replikation
  • Analyse von drei Parametern des MySQL-Replikationsproblems
  • Umfassende Analyse des MySql-Master-Slave-Replikationsmechanismus
  • MySQL Serie 13 MySQL-Replikation

<<:  Zusammenfassung wissenschaftlicher Grundlagen und Anregungen für Webdesign und -produktion

>>:  Docker5 - Vollfunktionaler Hafenlager-Bauprozess

Artikel empfehlen

Tipps zur Verwendung von DIV-Containern mit fester Höhe in IE6 und IE7

Es gibt viele Unterschiede zwischen IE6 und IE7 in...

Detaillierte Erläuterung des Lese-Commits der MySQL-Transaktionsisolationsebene

MySQL-Transaktionsisolationsebene anzeigen mysql&...

Detaillierte Erläuterung des automatischen Füllschreibens von CSS3-Flexboxen

In diesem Artikel wird hauptsächlich die Methode ...

Liste der allgemeinen MySql-Abfragebefehlsoperationen

In MySQL häufig verwendete Abfragebefehle: mysql&...

Ein Beispiel zum Schreiben eines großen Sonnenwettersymbols in reinem CSS

Wirkung Das Wirkungsdiagramm sieht wie folgt aus ...

HTML-Tabellen-Markup-Tutorial (43): VALIGN-Attribut der Tabellenüberschrift

In vertikaler Richtung können Sie die Ausrichtung...

Einführung in Docker-Container

1. Übersicht 1.1 Grundlegende Konzepte: Docker is...