Zum Inhalt springen
EuroVPSEuroVPS

Read-after-write-Konsistenz in einem Galera-Cluster

Ein Galera- oder Percona-XtraDB-Cluster zertifiziert einen Write beim Commit und wendet ihn auf den anderen Knoten einen Moment später an, und ein Read, der in diese Lücke geleitet wird, sieht die Vergangenheit.

Von EuroVPS EngineeringDer Maschinenraum

6 Min. Lesezeit
In diesem Artikel 6 Abschnitte
Kurz gesagt
  • In einem zertifizierungsbasierten Cluster bedeutet Commit, dass der Write auf jedem Knoten zertifiziert wurde, nicht, dass jeder Knoten ihn angewendet hat. Das Apply geschieht einen Moment später, typischerweise Dutzende bis einige Hundert Millisekunden.
  • Ein Read, der auf einen Knoten verteilt wird, der den Write noch nicht angewendet hat, liefert die alte Zeile zurück. In einem CMS liest sich das als verlorene Änderung: Der Redakteur speichert, lädt neu, sieht den alten Text und speichert erneut über die neuere Version. Nirgends erscheint ein Fehler.
  • wsrep_sync_wait schließt die Lücke, indem ein Read wartet, bis sein Knoten aufgeholt hat. Es kostet den Apply-Lag auf den Reads, die einem Write folgen, deshalb wird es auf die Sitzungen begrenzt, die es brauchen, und bleibt auf den Seiten aus, die ein Edge-Cache ausliefert.

Commit heißt zertifiziert, nicht angewendet

Ein Galera-Cluster führt eine Transaktion auf einem Knoten aus. Beim Commit sendet dieser Knoten das Write Set an das Cluster, jeder Knoten zertifiziert es gegen die bereits laufenden Write Sets, und das Commit kehrt zum Client zurück. Von diesem Moment an ist der Write im Cluster dauerhaft und überall identisch geordnet.

Was noch nicht geschehen ist, ist das Apply. Jeder Knoten nimmt das zertifizierte Write Set und wendet es in seinen eigenen Applier-Threads auf seine eigene Kopie der Daten an, kurz nachdem das Commit zurückgekehrt ist. Zwei Uhren laufen: Die Zertifizierung ist clusterweit und Teil des Commits, das Anwenden ist lokal und kommt danach. In einem gesunden Cluster liegt der Abstand zwischen beiden bei Dutzenden bis einigen Hundert Millisekunden. Er wächst bei Write-Spitzen, großen Transaktionen und Schemaänderungen und ist als wsrep_local_recv_queue ungleich null auf dem Knoten sichtbar, der zurückliegt.

Wohin der Read geht

Ein Cluster mit verteilten Reads schickt Reads dorthin, wo der Proxy es entscheidet. Eine Anfrage schreibt auf Knoten A. Die nächste Anfrage desselben Benutzers, einige Hundert Millisekunden später, liest auf Knoten B. Hat Knoten B das Write Set empfangen, aber noch nicht angewendet, antwortet er mit der Zeile, wie sie vor dem Write war. Aus Sicht von Knoten B ist die Antwort korrekt: Das ist sein committeter Zustand. Nichts wird protokolliert, nichts alarmiert, und der Lag-Monitor bleibt still, weil er gebaut ist, anhaltenden Lag zu erkennen, nicht die ersten hundert Millisekunden nach einer Transaktion.

Deshalb wirkt das Symptom zufällig. Es hängt davon ab, welchen Knoten der Balancer gewählt hat, wie schnell der Benutzer zurückkam und wie beschäftigt die Applier in diesem Augenblick waren.

Wie es in einer Anwendung aussieht

Das Muster ist ein Write, dem sofort ein Read desselben Benutzers folgt, der auf einem anderen Knoten landet. In einem CMS ist es der verschwundene Absatz: speichern, neu laden, alter Text, neu tippen, speichern, und das zweite Speichern überschreibt das erste. In einem Onlineshop ist es eine Bestellung, die auf der Bestätigungsseite nicht existiert. In einem Authentifizierungsablauf ist es ein Token, das gerade ausgestellt wurde und nicht gefunden wird.

Zwei andere Mechanismen erzeugen eine ähnliche Geschichte und sollten zuerst ausgeschlossen werden. Der Back-Forward-Cache eines Browsers kann eine veraltete Kopie eines Formulars wiederherstellen, und ein erneutes Speichern schreibt dann diese veraltete Kopie. Ein Plugin kann aus zwei Anfragen ein Read-Modify-Write auf derselben Zeile ausführen. Beides ist real, und keines davon ist das Cluster. Eine Schleife, die einen Zeitstempel auf einen Knoten schreibt und ihn von den anderen zurückliest, trennt sie in einer Minute.

Die Einstellung: wsrep_sync_wait

wsrep_sync_wait ist eine Bitmaske. Mit gesetztem Bit 1 wartet ein SELECT, bis der Knoten jedes bis zu diesem Moment empfangene Write Set angewendet hat, bevor er läuft. Der Read sieht dann garantiert alles, was irgendwo im Cluster vor seinem Start committet wurde. Sie kann für eine Sitzung gesetzt werden, der richtige Umfang für einen Redaktions- oder Checkout-Pfad, oder global, wenn die gesamte Workload empfindlich auf Read-after-write reagiert.

TERMINAL
-- for one session: the request path that writes and then reads
SET SESSION wsrep_sync_wait = 1;

-- for the whole node: my.cnf, under [mysqld]
wsrep_sync_wait = 1

Die Alternative ist Routing: Schicken Sie die Reads, die einem Write folgen, an den Knoten, der geschrieben hat, mit Query-Regeln im Proxy oder in der Anwendung. Das funktioniert für die Pfade, die es abdeckt. Ein Code-Pfad, den niemand geroutet hat, öffnet die Lücke wieder, und deshalb wird die Einstellung bevorzugt, wo der Preis bezahlt werden kann: Sie adressiert den Mechanismus, nicht einen Pfad durch ihn.

Was es kostet und wo Sie es bezahlen

Ein Read unter wsrep_sync_wait wartet darauf, dass der lokale Applier aufholt, zahlt also den Apply-Lag einmal pro Read, der einem Write folgt. In einem gesunden Cluster sind das Dutzende bis einige Hundert Millisekunden. Angemeldete Sitzungen, Admin- und Redaktionspfade und der Checkout sind die Stellen, an denen dieser Preis etwas kauft. Anonyme Seiten aus einem Edge-Cache berühren die Datenbank bei einem Treffer nicht und sind nicht betroffen. Die Einstellung wirkt ab der nächsten Anweisung und lässt sich auf demselben Weg zurücknehmen, sie kann also vor Ort mit der echten Workload gemessen statt geschätzt werden.

Wie Sie Ihr eigenes Cluster prüfen

Drei Messwerte entscheiden es. Ob Reads überhaupt warten. Wie weit ein Knoten bei einer Write-Spitze zurückfällt. Und wie oft ein knotenübergreifendes Read-after-write tatsächlich die Vergangenheit sieht, aus einer Schleife, die auf einen Knoten schreibt und auf den anderen liest.

TERMINAL
SHOW GLOBAL VARIABLES LIKE 'wsrep_sync_wait';        -- 0 means reads do not wait
SHOW GLOBAL STATUS LIKE 'wsrep_local_recv_queue';    -- received, not yet applied

Wir betreiben Percona-XtraDB-Cluster mit verteilten Reads hinter ProxySQL und HAProxy und können diese drei Fragen für jedes Cluster beantworten, das wir betreiben, einschließlich dessen, was die Einstellung auf dieser konkreten Workload kostet.

Klare Antworten

Ist die Galera-Replikation synchron?+

Die Zertifizierung ist es: Der Write wird auf jedem Knoten zertifiziert, bevor das Commit zurückkehrt. Das Apply auf jedem Knoten geschieht einen Moment später. Beide Hälften zählen, und in der zweiten wohnen die Read-after-write-Probleme.

Warum verliert mein CMS in einem Cluster Änderungen?+

Ein Read nach dem Speichern wurde an einen Knoten geleitet, der das Write Set empfangen, aber noch nicht angewendet hatte. Der Redakteur sah den alten Inhalt, tippte ihn neu und speicherte über die neuere Version. Es entsteht kein Fehler, deshalb wirkt es sporadisch.

Hilft es, den Cache zu leeren?+

In der Regel nicht. Der Cache hat gespeichert, was die Datenbank zurückgab, und für einen Moment gab die Datenbank die Vergangenheit zurück. Diagnostizieren Sie den Read-Pfad. Der Cache trägt hier das Symptom, er ist nicht die Ursache.

Was kostet wsrep_sync_wait?+

Den Apply-Lag, bezahlt auf Reads, die einem Write folgen, typischerweise Dutzende bis einige Hundert Millisekunden in einem gesunden Cluster. Seiten aus einem Edge-Cache sind nicht betroffen. Begrenzen Sie es pro Sitzung, um es nur dort zu bezahlen, wo es zählt.

Betreiben Sie ein Cluster mit verteilten Reads?

Sprechen Sie mit einem Ingenieur darüber, ob Read-after-write bei Ihnen aktiv ist und was es kostet.

Mit einem Ingenieur sprechen

Sie haben das Ende erreicht.

Setzen Sie das Gelesene um

Was betreiben Sie?

Erzählen Sie uns von Workload, Traffic und Anforderungen an die Wiederherstellung. Beginnen Sie mit dem Server-Konfigurator oder besprechen Sie die Details mit einem Ingenieur.

Geschrieben von den Ingenieuren, die die beschriebene Infrastruktur bauen und betreiben.
Mit einem Ingenieur sprechen
XIn

Noch 6 Min.