PostgreSQL- und verbindungsspezifische Schreibkonsistenzeinstellungen

Die Übersetzung des Artikels wurde speziell für die Studierenden des Kurses erstellt "Datenbank". Sind Sie daran interessiert, sich in diese Richtung zu entwickeln? Wir laden Sie dazu ein Tag der offenen TürHier sprechen wir ausführlich über das Programm, Besonderheiten des Online-Formats, Kompetenzen und Berufsaussichten, die Absolventen nach der Ausbildung erwarten.

PostgreSQL- und verbindungsspezifische Schreibkonsistenzeinstellungen

PostgreSQL- und verbindungsspezifische Schreibkonsistenzeinstellungen
Bei Compose beschäftigen wir uns mit vielen Datenbanken, was uns die Möglichkeit gibt, sich mit deren Funktionalität und Mängeln vertraut zu machen. Wenn wir lernen, die Funktionen neuer Datenbanken zu lieben, denken wir manchmal darüber nach, wie schön es wäre, wenn ähnliche Funktionen in den ausgereifteren Tools vorhanden wären, mit denen wir schon lange arbeiten. Eine der neuen Funktionen, die ich in PostgreSQL sehen wollte, war die konfigurierbare Schreibkonsistenz pro Verbindung im gesamten Cluster. Und wie sich herausstellt, haben wir es bereits und heute möchten wir Ihnen Informationen darüber geben, wie Sie es verwenden können.

Wozu brauche ich das?

Wie sich der Cluster verhalten soll, hängt von Ihrer Anwendung ab. Nehmen Sie zum Beispiel eine Rechnungszahlungs-App. Sie benötigen XNUMX % Konsistenz im gesamten Cluster, daher müssen Sie synchrone Commits aktivieren, damit Ihre Datenbank darauf wartet, dass alle Änderungen vorgenommen werden. Wenn es sich bei Ihrer Anwendung jedoch um ein schnell wachsendes soziales Netzwerk handelt, bevorzugen Sie wahrscheinlich eine schnelle Reaktion gegenüber einer XNUMX-prozentigen Konsistenz. Um dies zu erreichen, können Sie in Ihrem Cluster asynchrone Commits verwenden.

Treffen Sie Kompromisse

Sie müssen Kompromisse zwischen Datenkonsistenz und Leistung eingehen. PostgreSQL entfernt sich von der Konsistenz, da die Standardkonfiguration dann vorhersehbar und ohne unerwartete Überraschungen ist. Schauen wir uns nun die Kompromisse an.

Kompromiss 1: Leistung

Wenn der PostgreSQL-Cluster keine Konsistenz erfordert, kann er asynchron ausgeführt werden. Der Schreibvorgang erfolgt an den Cluster-Leader und Aktualisierungen werden einige Millisekunden später an seine Replikate gesendet. Wenn ein PostgreSQL-Cluster Konsistenz erfordert, muss er synchron ausgeführt werden. Der Schreibvorgang erfolgt an den Clusterleiter, der eine Aktualisierung an die Replikate sendet und auf die Bestätigung wartet, dass jeder geschrieben hat, bevor er eine Bestätigung an den Client sendet, der den Schreibvorgang initiiert hat, dass er erfolgreich war. Der praktische Unterschied zwischen diesen Ansätzen besteht darin, dass die asynchrone Methode zwei Netzwerk-Hops erfordert, während die synchrone Methode vier erfordert.

Kompromiss 2: Konsistenz

Auch das Ergebnis im Falle eines Führungsversagens wird bei diesen beiden Ansätzen unterschiedlich sein. Wenn die Arbeit asynchron ausgeführt wird und ein solcher Fehler auftritt, werden nicht alle Datensätze von den Replikaten festgeschrieben. Wie viel wird verloren gehen? Hängt von der Anwendung selbst und der Effizienz der Replikation ab. Durch die Erstellungsreplikation wird verhindert, dass ein Replikat zum Leader wird, wenn die darin enthaltene Informationsmenge 1 MB geringer ist als im Leader, d. h., während des asynchronen Vorgangs könnten möglicherweise bis zu 1 MB an Datensätzen verloren gehen.

Dies geschieht im synchronen Modus nicht. Wenn der Leader ausfällt, werden alle Replikate aktualisiert, da alle auf dem Leader bestätigten Schreibvorgänge auf den Replikaten bestätigt werden müssen. Das ist Konstanz.

Synchrones Verhalten ist in einer Abrechnungsanwendung sinnvoll, bei der Konsistenz einen klaren Vorteil im Kompromiss zwischen Konsistenz und Leistung hat. Das Wichtigste für eine solche Bewerbung sind valide Daten. Denken Sie nun an ein soziales Netzwerk, bei dem die Hauptaufgabe darin besteht, die Aufmerksamkeit des Benutzers zu erhalten, indem so schnell wie möglich auf Anfragen reagiert wird. In diesem Fall hat die Leistung mit weniger Netzwerk-Hops und weniger Wartezeiten auf Festschreibungen Priorität. Der Kompromiss zwischen Leistung und Konsistenz ist jedoch nicht der einzige, über den Sie nachdenken müssen.

Kompromiss 3: Abstürze

Es ist sehr wichtig zu verstehen, wie sich ein Cluster bei einem Ausfall verhält. Stellen Sie sich eine Situation vor, in der ein oder mehrere Replikate ausfallen. Wenn Commits asynchron verarbeitet werden, funktioniert der Leader weiterhin, d. h. er akzeptiert und verarbeitet Schreibvorgänge, ohne auf fehlende Replikate zu warten. Wenn die Replikate zum Cluster zurückkehren, holen sie den Anführer ein. Wenn die Replikate bei der synchronen Replikation nicht antworten, hat der Anführer keine Wahl und wartet weiterhin auf die Commit-Bestätigung, bis das Replikat zum Cluster zurückkehrt und den Schreibvorgang akzeptieren und festschreiben kann.

Eine Verbindung pro Transaktion?

Jede Anwendung benötigt eine andere Kombination aus Konsistenz und Leistung. Es sei denn natürlich, es handelt sich um unsere App zum Bezahlen von Rechnungen, die wir uns als vollkommen einheitlich vorstellen, oder um unsere fast flüchtige Social-Networking-App. In allen anderen Fällen gibt es Zeiten, in denen einige Vorgänge synchron und andere asynchron sein müssen. Möglicherweise möchten Sie nicht, dass das System wartet, bis eine an den Chat gesendete Nachricht festgeschrieben wird. Wenn jedoch eine Zahlung in derselben Anwendung verarbeitet wird, müssen Sie warten.

Alle diese Entscheidungen werden natürlich vom Anwendungsentwickler getroffen. Wenn Sie die richtigen Entscheidungen darüber treffen, wann Sie die einzelnen Ansätze nutzen, können Sie Ihren Cluster optimal nutzen. Es ist wichtig, dass der Entwickler auf SQL-Ebene für Verbindungen und Transaktionen zwischen ihnen wechseln kann.

Sicherstellung der Kontrolle in der Praxis

Standardmäßig sorgt PostgreSQL für Konsistenz. Dies wird durch den Serverparameter gesteuert synchronous_commit. Standardmäßig ist es in Position on, aber es gibt drei weitere Optionen: local, remote_write oder off.

Beim Einstellen des Parameters auf off Alle synchronen Commits werden gestoppt, auch auf dem lokalen System. Der lokale Parameter gibt den synchronen Modus für das lokale System an, Schreibvorgänge in Replikate werden jedoch asynchron ausgeführt. Remote_write geht sogar noch weiter: Schreibvorgänge auf Replikate erfolgen asynchron, werden jedoch zurückgegeben, wenn das Replikat den Schreibvorgang akzeptiert, ihn aber nicht auf die Festplatte geschrieben hat.

Indem wir die verfügbaren Optionen berücksichtigen, entscheiden wir uns für ein Verhalten und berücksichtigen es on – das sind synchrone Aufnahmen, die wir auswählen werden local für asynchrone Commits über das Netzwerk, während lokale Commits synchron bleiben.

Nun erklären wir Ihnen gleich, wie Sie dies einrichten, aber stellen Sie sich vor, wir richten es ein synchronous_commit в local für den Server. Wir fragten uns, ob es möglich sei, den Parameter zu ändern synchronous_commit im Handumdrehen, und es stellte sich heraus, dass es nicht nur möglich ist, sondern dass es sogar zwei Möglichkeiten gibt, dies zu tun. Die erste besteht darin, die Sitzung Ihrer Verbindung wie folgt festzulegen:

SET SESSION synchronous_commit TO ON;  
// Your writes go here

Alle nachfolgenden Schreibvorgänge in der Sitzung bestätigen Schreibvorgänge auf den Replikaten, bevor ein positives Ergebnis an den verbundenen Client zurückgegeben wird. Es sei denn natürlich, Sie ändern die Einstellung synchronous_commit wieder. Sie können einen Teil weglassen SESSION im Befehl, da es sich um den Standardwert handelt.

Die zweite Methode ist gut, wenn Sie nur sicherstellen möchten, dass Sie eine synchrone Replikation für eine einzelne Transaktion erhalten. In vielen Datenbanken der NoSQL-Generation gibt es das Konzept von Transaktionen nicht, in PostgreSQL jedoch schon. In diesem Fall starten Sie eine Transaktion und legen diese dann fest synchronous_commit в on bevor Sie den Eintrag für die Transaktion ausführen. COMMIT wird die Transaktion mit einem beliebigen Parameterwert festschreiben synchronous_commit, die zu diesem Zeitpunkt festgelegt wurde, obwohl es am besten ist, die Variable im Voraus festzulegen, um sicherzustellen, dass andere Entwickler verstehen, dass Schreibvorgänge nicht asynchron sind.

BEGIN;  
SET LOCAL synchronous_commit TO ON;  
// Your writes go here
COMMIT;  

Alle Transaktions-Commits werden nun als in Replikate geschrieben bestätigt, bevor die Datenbank eine positive Antwort an den verbundenen Client zurückgibt.

PostgreSQL konfigurieren

Zuvor haben wir uns ein PostgreSQL-System mit vorgestellt synchronous_commit, eingebaut in local. Um dies serverseitig realistisch darzustellen, müssen Sie zwei Serverkonfigurationsoptionen festlegen. Noch ein Parameter synchronous_standby_names wird zur Geltung kommen, wenn synchronous_commit wird dabei sein on. Es bestimmt, welche Replikate für synchrone Commits in Frage kommen, und wir setzen es auf *, was bedeutet, dass alle Replikate beteiligt sind. Diese Werte werden normalerweise in konfiguriert Konfigurationsdatei beim Hinzufügen:

synchronous_commit = local  
synchronous_standby_names='*'

Durch Einstellen des Parameters synchronous_commit in die Bedeutung localerstellen wir ein System, in dem lokale Festplatten synchron bleiben, Netzwerkreplikat-Commits jedoch standardmäßig asynchron sind. Es sei denn natürlich, wir entscheiden uns dafür, diese Commits synchron zu machen, wie oben gezeigt.

Wenn Sie die Entwicklung verfolgt haben Gouverneursprojekt, vielleicht sind Ihnen einige kürzliche Änderungen aufgefallen (1, 2), wodurch Governor-Benutzer diese Parameter testen und ihre Konsistenz überwachen konnten.

Noch ein paar Worte...

Noch vor einer Woche hätte ich Ihnen gesagt, dass es unmöglich ist, PostgreSQL so fein abzustimmen. Da bestand Kurt, ein Mitglied des Compose-Plattformteams, darauf, dass eine solche Möglichkeit bestehe. Er besänftigte meine Einwände und fand sie in der PostgreSQL-Dokumentation Folgende:

PostgreSQL- und verbindungsspezifische Schreibkonsistenzeinstellungen

Diese Einstellung kann jederzeit geändert werden. Das Verhalten einer Transaktion wird durch die zum Zeitpunkt des Commits gültige Einstellung bestimmt. Daher ist es möglich und nützlich, dass einige Transaktionen synchron und andere asynchron festgeschrieben werden. Zum Beispiel, um einen zu erzwingen multistatement Wenn der Standardwert des Parameters umgekehrt ist, wird die Transaktion so festgelegt, dass Commits asynchron ausgeführt werden SET LOCAL synchronous_commit TO OFF in einer Transaktion.

Mit dieser kleinen Änderung an der Konfigurationsdatei haben wir den Benutzern die Kontrolle über deren Konsistenz und Leistung gegeben.

Source: habr.com

Kommentar hinzufügen