Ist die MySQL-Replikation von einer Verbindung mit hoher Latenz betroffen?

11

Wir haben ein Vanilla-Master- und Slave-MySQL-Setup, das sich in verschiedenen Rechenzentren befindet, und einen weiteren Slave im selben Rechenzentrum wie der Master.

Die Bandbreite zwischen dem Rechenzentrum ist ziemlich hoch (in den von uns durchgeführten Netzwerk-Benchmarks können wir 15 MB / Sekunde erreichen), aber die Latenz beträgt ungefähr 28 ms. Es ist keineswegs hoch, aber es ist viel höher als die Latenz von weniger als einer Sekunde im selben Rechenzentrum.

Gelegentlich treten beim Entfernen des Slaves schwerwiegende Verzögerungen (2000 Sekunden und mehr) auf, während der lokale Slave auf dem neuesten Stand bleibt. Wenn Sie sich den verzögerten Remote-Slave ansehen, verbringt der SQL-Thread normalerweise die Zeit damit, darauf zu warten, dass der E / A-Thread das Relay-Protokoll aktualisiert. Der Meister zeigt gleichzeitig "Warten auf Netz" oder ähnliches.

Es bedeutet also, dass es sich um ein Netzwerk handelt, aber wir haben zu diesem Zeitpunkt noch freie Bandbreite.

Meine Frage ist : Kann die Latenz zwischen den Rechenzentren die Replikationsleistung beeinflussen? Streamen die Slave-Io-Threads die Ereignisse nur so lange, bis der Master aufhört, sie zu senden, oder bündelt er den Master irgendwie zwischen Ereignissen?

Shlomoid
quelle
2000 Sekunden? Also eine Verzögerung von 33 Minuten?
Richard
Ja ... Es geht den ganzen Tag rauf und runter.
Shlomoid
2
+1, weil ich diese Art von Fragen auf dieser Seite liebe. Bitte informieren Sie andere, die mit Fragen dieser Art auf diese Website kommen !!!
RolandoMySQLDBA

Antworten:

7

Die direkte Antwort auf Ihre Frage lautet Ja, hängt jedoch von der Version von MySQL ab, die Sie ausführen. Vor MySQL 5.5 würde die Replikation wie folgt funktionieren:

  • Master Führt SQL aus
  • Der Master zeichnet das SQL-Ereignis in seinen Binärprotokollen auf
  • Slave liest SQL-Ereignis aus binären Masterprotokollen
  • Slave speichert SQL-Ereignisse in seinen Relay-Protokollen über E / A-Thread
  • Slave liest das nächste SQL-Ereignis aus dem Relaisprotokoll über den SQL-Thread
  • Slave Führt SQL aus
  • Der Slave bestätigt den Master für die vollständige Ausführung des SQL-Ereignisses

Ab MySQL 5.5 unter Verwendung der semisynchronen Replikation würde die Replikation nun wie folgt funktionieren:

  • Master Führt SQL aus
  • Der Master zeichnet das SQL-Ereignis in seinen Binärprotokollen auf
  • Slave liest SQL-Ereignis aus binären Masterprotokollen
  • Slave bestätigt Master des Empfangs des SQL-Ereignisses
  • Slave speichert SQL-Ereignisse in seinen Relay-Protokollen über E / A-Thread
  • Slave liest das nächste SQL-Ereignis aus dem Relaisprotokoll über den SQL-Thread
  • Slave Führt SQL aus
  • Der Slave bestätigt den Master für die vollständige Ausführung des SQL-Ereignisses

Dieses neue Paradigma ermöglicht es einem Sklaven, näher an seinen Meister zu synchronisieren.

Ungeachtet dessen kann die Latenz innerhalb des Netzwerks die MySQL Semisync-Replikation bis zu dem Punkt behindern, an dem sie zur alten asynchronen Replikation zurückkehrt. Warum ? Wenn ein Timeout auftritt, ohne dass ein Slave die Transaktion bestätigt hat, kehrt der Master zur asynchronen Replikation zurück. Wenn mindestens ein semisynchroner Slave aufholt, kehrt der Master zur semisynchronen Replikation zurück.

UPDATE 2011-08-08 14:22 EDT

Die Konfiguration der semisynchronen Replikation von MySQL 5.5 ist unkompliziert

Schritt 1) ​​Fügen Sie diese vier (4) Zeilen zu /etc/my.cnf hinzu

[mysqld]
plugin-dir=/usr/lib64/mysql/plugin
#rpl_semi_sync_master_enabled
#rpl_semi_sync_master_timeout=5000
#rpl_semi_sync_slave_enabled

Schritt 2) Starten Sie MySQL neu

service mysql restart

Schritt 3) Führen Sie diese Befehle im MySQL-Client aus

INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
INSTALL PLUGIN rpl_semi_sync_slave  SONAME 'semisync_slave.so';

Schritt 4) Kommentieren Sie die drei Optionen rpm_semi_sync nach der Option plugin-dir aus

[mysqld]
plugin-dir=/usr/lib64/mysql/plugin
rpl_semi_sync_master_enabled
rpl_semi_sync_master_timeout=5000
rpl_semi_sync_slave_enabled

Schritt 5) Starten Sie MySQL neu

service mysql restart

Alles erledigt !!! Richten Sie jetzt einfach MySQL Replication wie gewohnt ein.

RolandoMySQLDBA
quelle
Ich bin mir nicht sicher über die letzte Stufe der asynchronen Replikation - ich glaube nicht, dass der Master weiß, wie weit jeder Slave gekommen ist. Soweit ich weiß, können sie nach einem beliebigen Teil des gewünschten Binärprotokolls fragen. Haben Sie eine Referenz dafür?
Shlomoid
Außerdem verwenden wir die standardmäßige asynchrone Replikation in MySQL, nicht den asynchronen Typ, der absichtlich durch die Installation von Plugins und Ähnlichem aktiviert werden muss. Ich versuche zu verstehen, ob Ereignisse von der Startposition im Protokoll im Net-Cat-Stil in den Slave geleitet werden oder ob für jedes Ereignis ein Austausch zwischen Master und Slave stattfindet, der unter einer solchen Latenz leiden kann.
Shlomoid
Ich empfehle auf jeden Fall die Verwendung von MySQL 5.5, um diese neue Form der MySQL-Replikation sowie die Verbesserungen von InnoDB zu nutzen.
RolandoMySQLDBA
1
Ja, natürlich verwenden wir MySQL 5.5, aber dies ist nicht der Standardreplikationstyp. Sie müssen eine ganze Konfigurationsprozedur durchlaufen, Plugins installieren und so weiter, damit es halbsynchron funktioniert.
Shlomoid
2

Mir gefällt sehr, wie Rolando die Abfolge der Operationen beschreibt, die eine Replikation ausführt. Ich denke jedoch, es wäre klarer, wenn wir eine weitere Komponente hinzufügen - den Client.

Mit dem Client kann die Reihenfolge der Operationen für die asynchrone Replikation wie folgt sein:

  1. Der Client sendet die SQL-Abfrage (z. B. Einfügen) mithilfe von Transaktionen an den Master

  2. Der Master führt die Transaktion aus. Im Erfolgsfall wird der Datensatz auf der Festplatte gespeichert, die Transaktion wird jedoch noch nicht festgeschrieben.

  3. Der Master zeichnet das Einfügeereignis im Master-Binärprotokoll auf. Wenn der Master es nicht im Binärprotokoll speichern konnte, wurde die Transaktion zurückgesetzt.

  4. Der Client erhält eine Antwort vom Master (Erfolg oder Rollback).

  5. Bei erfolgreichem Transaktionsvorgang liest der Dump-Thread auf dem Master das Ereignis aus dem Binärprotokoll und sendet es an den Slave-E / A-Thread.

  6. Der Slave-E / A-Thread empfängt das Ereignis und schreibt es an das Ende der Relay-Protokolldatei.

  7. Sobald das Ereignis in das Relay-Protokoll aufgenommen wurde, führt der Slave-SQL-Thread
    das Ereignis aus, um die Änderungen auf die Datenbank auf dem Slave anzuwenden.

In diesem Szenario kümmert sich der Master nicht um den Slave und der Client weiß nur, dass etwas auf dem Slave nicht stimmt, indem er den Befehl "SHOW SLAVE STATUS" manuell ausführt.

Im Fall einer halbsynchronen Replikation kann die Reihenfolge der Operationen wie folgt sein:

  1. Der Client sendet die SQL-Abfrage (z. B. Einfügen) mithilfe von Transaktionen an den Master.

  2. Der Master führt die Transaktion aus. Im Erfolgsfall wird der Datensatz auf der Festplatte gespeichert, die Transaktion wird jedoch nicht festgeschrieben.

  3. Der Master zeichnet das Einfügeereignis im Master-Binärprotokoll auf. Wenn der Master es nicht im Binärprotokoll speichern konnte, wird die Transaktion zurückgesetzt und der Client erhält die Antwort nur im Fall eines Rollbacks.

  4. Aufgrund des Erfolgs der Transaktion auf dem Master liest der Dump-Thread auf dem Master das Ereignis aus dem Binärprotokoll und sendet es an den Slave-E / A-Thread.

  5. Der Slave-E / A-Thread empfängt das Ereignis und schreibt es an das Ende der Relay-Protokolldatei.

  6. Slave Bestätigt den Master der Aufzeichnung des Ereignisses in der Relaisprotokolldatei.

  7. Der Master schreibt die Einfügetransaktion fest.

  8. Der Kunde erhält die Antwort vom Master (Erfolg).

  9. Sobald das Ereignis in das Relay-Protokoll aufgenommen wurde, führt der Slave-SQL-Thread
    das Ereignis aus. Master und Client wissen nicht, ob die Ausführung erfolgreich war oder nicht.

Die halbsynchrone Replikation löste einen wichtigen Fall, als Slave oder Netzwerk starben und der Master fortfuhr. Dann stirbt der Master und Sie möchten den alten Slave als neuen Master neu starten, nur weil Sie diesen Knoten repariert haben.

Sie haben diesen Knoten als neuen Master gestartet, den alten Master repariert und möchten ihn nun als Slave verwenden. Dieser Knoten hat noch die Daten, aber wenn der neue Slave an der Position startet, an der der neue Master gestartet wurde, gibt es doppelte Datensätze.

Wenn die Wartezeit unendlich ist, ist die binäre Protokollposition des Masters immer mit der Protokollposition des Slave-Relais synchron, vorausgesetzt, alle Abfragen auf dem Slave waren erfolgreich. Wie realistisch diese Annahme?

Ich finde es sehr realistisch. Einer der häufigsten Fälle eines Slave-Abfragefehlers ist "doppelter Datensatz". Woher kam der doppelte Datensatz zum Slave, wenn der Master ihn nicht hatte? Es kam von einer falschen Position, die dem Sklaven gegeben wurde, um mit der Replikation zu beginnen. Die Startreplikationsposition enthielt den Datensatz, der bereits repliziert wurde. Bei einer halbsynchronen Replikation tritt diese Situation nicht auf.

Jacob Nikom

Jacob Nikom
quelle
1

Qualifikation : Ich bin kein MySQL-Benutzer, daher ist dies meistens nur meine Recherche im Internet.

Wie Sie sicher wissen, besteht die größte Einschränkung der MySQL-Replikation darin, dass es sich um Single-Threaded handelt. Während der Thread damit beschäftigt ist, Daten an den internen Slave zu senden, kann er keine Daten an den Remote-Slave senden. Dies ist per hier .


Per hier :

Eine Sache, die Sie sicherstellen müssen, ist die Reduzierung Ihrer Transaktionszeit. Auf diese Weise hat Ihr Replikationsthread die Möglichkeit, sich über die Vorgänge in der Datenbank zu informieren. Sie möchten, dass Ihre Transaktionen so kurz wie möglich sind.

Eine Möglichkeit, dies zu tun, besteht darin, Abfragen zu zerhacken. Begrenzen Sie die durch UPDATE oder DELETE geänderten Zeilen mithilfe von WHERE-Klauseln. Wenn Sie dies in eine Schleife einfügen, können Sie die Liste durchlaufen und die Transaktion jedes Mal starten und festschreiben. (UPDATE / DELETE das erste Drittel, das zweite Drittel, dann das letzte Drittel jeweils in einer eigenen Transaktion.) Ich persönlich würde dringend davon abraten, da Sie sich der Möglichkeit öffnen, dass sich die Daten in der Tabelle zwischen Transaktionen ändern. Es ist jedoch möglich, diese Leistung zu verbessern, wenn Sie sicher sind, dass niemand anderes mit der Tabelle herumspielt (und dies niemals tun wird) .

Eine andere Möglichkeit besteht darin, diese lang laufenden Transaktionen nicht zu replizieren, sondern sie sowohl auf dem Master (der auf den lokalen Slave repliziert) als auch auf dem Remote-Slave separat auszuführen. Dies würde den Replikationsthread freigeben, sodass er nicht bis zur 30-Minuten-Marke blockiert.


Per hier :

Eine letzte Möglichkeit wäre, die Größe Ihrer TCP-Puffer zu optimieren. Ziel ist es, die Anzahl der Kommunikationen zwischen Master und Slave zu reduzieren. Dies könnte dazu beitragen, die Latenz zu verringern.

Persönlich würde ich dies versuchen, wenn alles andere fehlschlägt. Ich vermute, dass das Problem eher durch das Single-Threaded-Replikationssystem als durch eine Netzwerklatenz verursacht wird. Netzwerke haben normalerweise eine Zeitüberschreitung lange vor der 30-Minuten-Marke. (30 Minuten?!)


JHammerbs köstliche Lesezeichen mehrere Links für die MySQL-Replikation, die Sie möglicherweise auch überprüfen möchten.

Ich hoffe das hilft.

Richard
quelle
1
Sie erhalten eine +1 für die Angabe, wie MySQL Replication Single-Threaded ist, aber ich muss Ihre Aussage wie folgt qualifizieren: MySQL Replication ist Dual-Threaded mit einem E / A-Thread zum Herunterladen von SQL-Ereignissen vom Master zum Slave und einem SQL-Thread zur Verarbeitung die SQL-Ereignisse lokal auf dem Slave. Die Übertragung der SQL-Ereignisse erfolgt jedoch mit einem Thread, was für diese Frage kontextuell korrekt ist.
RolandoMySQLDBA
2
Übrigens Bitte verwenden Sie LIMIT nicht mit UPDATE- und DELETE-Anweisungen, da die Reihenfolge der zu aktualisierenden oder zu löschenden Zeilen auf dem Slave möglicherweise nicht mit der auf dem Master übereinstimmt. In der Tat werden Warnmeldungen dazu im Fehlerprotokoll wie "Statement Not BinLog-Safe" angezeigt.
RolandoMySQLDBA
Oh, ein guter Punkt, um LIMIT nicht mit UPDATE und DELETE zu verwenden. Ich werde meine Antwort ändern, um das zu entfernen.
Richard