Die Übersetzung des Artikels wurde speziell für die Studierenden des Kurses erstellt. . Möchten Sie sich in diesem Bereich weiterentwickeln? Wir laden Sie ein zu , wo wir Ihnen das Programm, die Besonderheiten des Online-Formats, die Kompetenzen und die Karrierechancen, die Absolventen nach dem Studium erwarten, ausführlich erklären.

PostgreSQL und die Anpassung der Konsistenz von Aufzeichnungen für jede spezifische Verbindung
Bei Compose arbeiten wir mit vielen Datenbanken, was uns ermöglicht, deren Funktionalitäten und Schwächen genauer kennenzulernen. Während wir beginnen, die funktionalen Eigenschaften neuer Datenbanken zu schätzen, denken wir manchmal daran, wie schön es wäre, wenn ähnliche Funktionen auch in den reiferen Tools vorhanden wären, mit denen wir schon lange arbeiten. Eine der neuen Funktionen, die wir uns in PostgreSQL gewünscht hatten, war die anpassbare Konsistenz von Aufzeichnungen pro Verbindung im gesamten Cluster. Und wie sich herausstellte, haben wir sie bereits, und heute möchten wir Ihnen Informationen darüber geben, wie Sie diese nutzen können.
Warum ist das für mich wichtig?
Das Verhalten eines Clusters hängt von Ihrer Anwendung ab. Nehmen wir als Beispiel eine Rechnungszahlungsanwendung. Hier benötigen Sie hundertprozentige Konsistenz im Cluster, was bedeutet, dass Sie synchrone Commits aktivieren müssen, damit Ihre Datenbank wartet, bis alle Änderungen vorgenommen wurden. Wenn jedoch Ihre Anwendung ein schnell wachsendes soziales Netzwerk ist, werden Sie wahrscheinlich eine schnelle Reaktionszeit anstelle von hundertprozentiger Konsistenz bevorzugen. Um dies zu erreichen, können Sie in Ihrem Cluster asynchrone Commits verwenden.
Lernen Sie den Kompromiss kennen
Sie stehen vor dem Kompromiss zwischen Datenkonsistenz und Leistung. PostgreSQL bewegt sich von der Konsistenz weg, da die Standardkonfiguration in diesem Fall vorhersehbar und ohne unerwartete Überraschungen ist. Lassen Sie uns nun die Kompromisse kennenlernen.
Kompromiss 1: Leistung
Wenn ein PostgreSQL-Cluster keine Konsistenz benötigt, kann er durchaus asynchron betrieben werden. Die Schreiboperation erfolgt beim Cluster-Primärserver, und dessen Replikate erhalten nach wenigen Millisekunden die Updates. Wenn der PostgreSQL-Cluster jedoch Konsistenz benötigt, muss er synchron arbeiten. Die Schreiboperation wird beim Primärserver ausgeführt, der die Updates an die Replikate sendet und auf eine Bestätigung wartet, dass jedes Replikat die Schreiboperation erfolgreich durchgeführt hat, bevor eine Bestätigung an den Client gesendet wird, der die Schreiboperation initiiert hat, dass die Operation 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
Das Resultat im Falle eines Ausfalls des Leaders in diesen beiden Ansätzen wird ebenfalls unterschiedlich sein. Wenn die Aufgaben asynchron ausgeführt werden, sind bei einem solchen Fehler nicht alle Aufzeichnungen in den Replikaten gespeichert. Wie viel wird verloren gehen? Das hängt von der Anwendung selbst und der Effizienz der Replikation ab. Die Compose-Replikation verhindert, dass ein Replikat zum Leader wird, wenn die Datenmenge darin 1 MB geringer ist als beim Leader, was bedeutet, dass potenziell bis zu 1 MB an Aufzeichnungen bei asynchronem Betrieb verloren gehen kann.
Im synchronen Modus passiert das nicht. Wenn der Leader ausfällt, werden alle Replikate aktualisiert, da jede auf dem Leader bestätigte Aufzeichnung auch in den Replikaten bestätigt werden muss. Das ist die Konsistenz.
Synchrones Verhalten ist sinnvoll in einer Rechnungserstellungsanwendung, wo Konsistenz klarer Vorteil bietet, um einen Kompromiss zwischen Konsistenz und Leistung zu finden. Das Wichtigste für eine solche Anwendung sind gültige Daten. Denken Sie jetzt an ein soziales Netzwerk, in dem die Hauptaufgabe darin besteht, die Aufmerksamkeit des Nutzers zu halten, indem Anfragen so schnell wie möglich beantwortet werden. In diesem Fall hat die Leistung mit weniger Netzwerk-Hops und kürzeren Wartezeiten auf Commits oberste Priorität. Doch der Kompromiss zwischen Leistung und Konsistenz ist nicht der einzige, über den man nachdenken muss.
Kompromiss 3: Ausfälle
Es ist entscheidend zu verstehen, wie sich ein Cluster während eines Ausfalls verhält. Betrachten wir die Situation, in der eine oder mehrere Replikate ausfallen. Wenn die Commits asynchron verarbeitet werden, wird der Leader weiterhin funktionieren, das heißt, er wird Daten entgegennehmen und verarbeiten, ohne auf die fehlenden Replikate zu warten. Wenn die Replikate wieder im Cluster sind, holen sie den Leader auf. Bei synchroner Replikation, wenn die Replikate nicht antworten, hat der Leader keine Wahl und wird weiterhin auf die Bestätigung des Commits warten, bis das Replikat wieder im Cluster ist und die Daten annehmen und bestätigen kann.
Eine Verbindung pro Transaktion?
Jede Anwendung benötigt eine spezifische Balance zwischen Konsistenz und Leistung. Es sei denn, sie ist unsere Buchhaltungsanwendung, die wir uns als vollkommen konsistent vorstellen, oder unsere fast flüchtige Social-Media-Anwendung. In allen anderen Fällen gibt es Momente, in denen einige Operationen synchron und andere asynchron ausgeführt werden müssen. Sie möchten wahrscheinlich nicht, dass das System darauf wartet, dass eine im Chat gesendete Nachricht festgeschrieben wird, aber wenn in derselben Anwendung eine Zahlung erfolgt, muss es eben warten.
All diese Entscheidungen trifft natürlich der Anwendungsentwickler. Die richtigen Entscheidungen darüber, wann welcher Ansatz angewendet werden soll, helfen, das Beste aus dem Cluster herauszuholen. Es ist wichtig, dass der Entwickler auf der SQL-Ebene sowohl für Verbindungen als auch für Transaktionen zwischen den Ansätzen wechseln kann.
Die praktische Kontrolle gewährleisten
PostgreSQL sorgt standardmäßig für Konsistenz. Dies wird durch den Serverparameter synchronous_commitkontrolliert. Standardmäßig ist er auf oneingestellt, aber es gibt drei weitere Optionen: local, remote_write oder off.
Beim Setzen des Parameters auf off Alle synchronen Commits werden gestoppt, auch im lokalen System. Der Parameter in local definiert den synchronen Modus für das lokale System, jedoch erfolgen die Aufzeichnungen in den Replikaten asynchron. Remote_write geht sogar noch weiter: Die Aufzeichnungen in den Replikaten erfolgen asynchron, aber sie werden zurückgegeben, sobald das Replikat die Aufzeichnung akzeptiert hat, aber sie noch nicht auf die Festplatte geschrieben wurde.
Wenn wir das vorhandene Spektrum an Optionen betrachten, wählen wir das Verhalten und berücksichtigen dabei, dass on – dies synchrone Aufzeichnungen sind, wählen wir local für asynchrone Commits über das Netzwerk, während die lokalen Commits synchron bleiben.
Nun werden wir Ihnen zeigen, wie Sie dies im Handumdrehen einrichten können, aber stellen Sie sich vor, dass wir synchronous_commit in local für den Server installiert haben. Wir fragten uns, ob wir den Parameter synchronous_commit dynamisch ändern können, und es stellte sich heraus, dass dies nicht nur möglich ist, sondern dafür gibt es sogar zwei verschiedene Möglichkeiten. Die erste Möglichkeit besteht darin, Ihre Verbindungssitzung wie folgt einzustellen:
SET SESSION synchronous_commit TO ON;
// Hier kommen Ihre SchreibvorgängeAlle nachfolgenden Aufzeichnungen in der Sitzung bestätigen die Schreiboperationen für die Replikate, bevor sie ein positives Ergebnis an den verbundenen Client zurückgeben. Es sei denn, Sie ändern die Einstellung synchronous_commit wieder. Sie können den Teil SESSION weglassen. im Team, da es die Standardbedeutung haben wird.
Die zweite Methode ist gut, wenn Sie einfach sicherstellen möchten, dass Sie eine synchronisierte Replikation für eine Transaktion erhalten. In vielen NoSQL-Datenbanken gibt es das Konzept von Transaktionen nicht, aber in PostgreSQL existiert es. In diesem Fall starten Sie eine Transaktion und setzen dann synchronous_commit in on vor der Durchführung des Schreibens für die Transaktion. BESTÄTIGEN die Transaktion mit einem beliebigen Wert des Parameters synchronous_commit, der zu diesem Zeitpunkt gesetzt wurde, obwohl es am besten ist, die Variable im Voraus zu definieren, um sicherzustellen, dass andere Entwickler verstehen, dass die Aufzeichnungen nicht asynchron sind.
BEGIN;
SET LOCAL synchronous_commit TO ON;
// Ihre Schreibvorgänge kommen hierhin
COMMIT; Alle Transaktionscommits werden jetzt so bestätigt, als wären sie in Repliken geschrieben, noch bevor die Datenbank eine positive Antwort an den verbundenen Client zurückgibt.
PostgreSQL-Konfiguration
Vorher haben wir uns ein PostgreSQL-System mit synchronous_commit, eingestellt auf local. Damit dies auf der Serverseite wirksam wird, müssen Sie zwei Serverkonfigurationsparameter setzen. Ein weiterer Parameter synchronous_standby_names wird in Kraft treten, wenn synchronous_commit in on. Es bestimmt, welche Replikate für synchronisierte Commits berechtigt sind, und wir werden es auf *, was bedeutet, dass alle Replikate in Betrieb genommen werden. Diese Werte werden normalerweise in der durch Hinzufügen von:
synchronous_commit = local
synchronous_standby_names='*'Durch das Setzen der Option synchronous_commit auf local, schaffen wir ein System, bei dem lokale Festplatten synchron bleiben, während Commits von Netzwerkreplikaten standardmäßig asynchron sind. Es sei denn, wir entscheiden uns, diese Commits synchron zu gestalten, wie oben gezeigt.
Wenn Sie die Entwicklungen des verfolgt haben, könnten Ihnen einige kürzliche Änderungen aufgefallen sein (, ), die es den Benutzern von Governor erlauben, diese Optionen zu testen und ihre Konsistenz zu steuern.
Ein paar Worte mehr…
Vor einer Woche hätte ich Ihnen gesagt, dass es unmöglich sei, PostgreSQL so fein abzustimmen. Damals insistierte Kurt, ein Mitglied des Compose-Plattformenteams, dass diese Möglichkeit besteht. Er beruhigte meine Bedenken und fand in der PostgreSQL-Dokumentation :

Dieser Parameter kann jederzeit geändert werden. Das Verhalten für jede Transaktion wird durch die Einstellung bestimmt, die zum Zeitpunkt des Commits aktiv ist. Daher kann es sinnvoll und nützlich sein, für einige Transaktionen die Commits synchron und für andere asynchron durchzuführen. Um beispielsweise eine Multistatement Transaktion asynchron zu committen, wenn der Standardwert das Gegenteil ist, geben Sie SET LOCAL synchronous_commit TO OFF in der Transaktion an.
Mit dieser kleinen Modifikation in der Konfigurationsdatei haben wir den Nutzern die Kontrolle über ihre Konsistenz und Leistung gegeben.
Quelle: habr.com
