PostgreSQL- und Datensatzkonsistenzeinstellungen für jede bestimmte Verbindung

Die Übersetzung des Artikels wurde speziell für Studenten des Kurses "Datenbank" vorbereitet. Ist es interessant, sich in diese Richtung zu entwickeln? Wir laden Sie zum Tag der offenen Tür ein , an dem wir ausführlich über das Programm, die Merkmale des Online-Formats, die Kompetenzen und die Karriereaussichten sprechen, die die Absolventen nach der Ausbildung erwarten.



PostgreSQL- und Datensatzkonsistenzeinstellungen für jede bestimmte Verbindung
Bei Compose müssen wir uns mit vielen Datenbanken auseinandersetzen, was uns die Möglichkeit gibt, mehr über deren Funktionalität und Nachteile zu erfahren. Wenn wir lernen, die Funktionsmerkmale neuer Datenbanken zu lieben, denken wir manchmal darüber nach, wie gut es wäre, wenn ähnliche Funktionen in ausgereifteren Tools vorhanden wären, mit denen wir schon lange arbeiten. Eine der neuen Funktionen, die PostgreSQL sehen wollte, war die benutzerdefinierte Schreibkonsistenz im gesamten Cluster. Und wie sich herausstellte, haben wir es bereits und heute möchten wir Ihnen Informationen darüber mitteilen, wie Sie es verwenden können.


Wozu brauche ich das?


Wie sich ein Cluster verhalten soll, hängt von Ihrer Anwendung ab. Nehmen Sie zum Beispiel einen Antrag auf Bezahlung von Rechnungen. Sie benötigen eine 100% ige Konsistenz im Cluster, daher müssen Sie synchrone Commits aktivieren, damit Ihre Datenbank auf alle Änderungen wartet. Wenn es sich bei Ihrer Anwendung jedoch um ein schnell wachsendes soziales Netzwerk handelt, bevorzugen Sie wahrscheinlich eine 100% ige Konsistenz mit einer schnellen Antwort. Um dies zu erreichen, können Sie asynchrone Commits in Ihrem Cluster verwenden.


Treffen Sie den Kompromiss


Sie müssen Kompromisse zwischen Datenkonsistenz und Leistung eingehen. PostgreSQL geht von der Konsistenz aus, da die Standardkonfiguration in diesem Fall vorhersehbar und ohne unerwartete Überraschungen ist. Und jetzt werden wir uns mit Kompromissen vertraut machen.


Kompromiss 1: Leistung


Wenn der PostgreSQL-Cluster keine Konsistenz erfordert, funktioniert er möglicherweise asynchron. Die Aufzeichnung erfolgt an den Clusterleiter, und nach einigen Millisekunden werden Aktualisierungen an seine Replikate gesendet. Wenn für einen PostgreSQL-Cluster Konsistenz erforderlich ist, sollte diese synchron funktionieren. Der Datensatz wird im Leiter des Clusters erstellt, der Aktualisierungen an die Replikate sendet und auf die Bestätigung wartet, dass alle den Datensatz erstellt haben, bevor eine Bestätigung an den Client gesendet wird, der den Datensatz initiiert hat, dass er erfolgreich war. Der praktische Unterschied zwischen diesen Ansätzen besteht darin, dass das asynchrone Verfahren zwei Netzwerksprünge erfordert, während das synchrone Verfahren vier erfordert.


Kompromiss 2: Konsistenz


Das Ergebnis im Falle einer Fehlfunktion eines Leiters bei diesen beiden Ansätzen ist ebenfalls unterschiedlich. Wenn die Arbeit asynchron ausgeführt wird, werden bei Auftreten eines solchen Fehlers nicht alle Datensätze von Replikaten festgeschrieben. Wie viel wird verloren gehen? Hängt von der Anwendung selbst und der Replikationseffizienz ab. Durch die Compose-Replikation wird verhindert, dass das Replikat zum Leader wird, wenn die darin enthaltene Informationsmenge 1 MB geringer ist als im Leader, dh bis zu 1 MB Datensätze können möglicherweise während des asynchronen Betriebs verloren gehen.


Im synchronen Modus geschieht dies nicht. Wenn der Leader ausfällt, werden alle Replikate aktualisiert, da alle auf dem Leader bestätigten Datensätze in den Replikaten bestätigt werden müssen. Hier ist es - Kohärenz.


Es ist sinnvoll, synchrones Verhalten in einer Anwendung zum Bezahlen von Rechnungen zu verwenden, wobei Konsistenz einen klaren Vorteil darin hat, einen Kompromiss zwischen Konsistenz und Leistung zu finden. Das Wichtigste für eine solche Anwendung sind gültige Daten. Denken Sie jetzt an das soziale Netzwerk, in dem die Hauptaufgabe darin besteht, die Aufmerksamkeit des Benutzers zu erhalten und auf Anfragen so schnell wie möglich zu reagieren. In diesem Fall hat die Leistung mit weniger Netzwerksprüngen und weniger Wartezeiten Priorität. Der Kompromiss zwischen Leistung und Konsistenz ist jedoch nicht der einzige, über den man nachdenken muss.


Kompromiss 3: Fehler


Es ist sehr wichtig zu verstehen, wie sich der Cluster während eines Fehlers verhält. Stellen Sie sich eine Situation vor, in der ein oder mehrere Replikate fehlschlagen. Wenn Commits asynchron verarbeitet werden, funktioniert der Leader weiterhin, dh er empfängt und verarbeitet Datensätze, ohne auf fehlende Replikate zu warten. Wenn die Replikate zum Cluster zurückkehren, holen sie den Anführer ein. Wenn bei der synchronen Replikation die Replikate nicht antworten, hat der Leiter keine Wahl und wartet weiterhin auf die Bestätigung des Commits, bis das Replikat zum Cluster zurückkehrt und den Datensatz akzeptieren und bestätigen kann.


Eine Verbindung pro Transaktion?


Jede Anwendung benötigt eine spezielle Kombination aus Konsistenz und Leistung. Es sei denn natürlich, es handelt sich um unsere Abrechnungsanwendung, die wir für vollständig konsistent halten, oder um unsere fast kurzlebige Anwendung für soziale Netzwerke. In allen anderen Fällen kann es vorkommen, dass einige Vorgänge synchron und andere asynchron sein müssen. Möglicherweise möchten Sie nicht, dass das System darauf wartet, dass die an den Chat gesendete Nachricht geschlossen wird. Wenn die Zahlung jedoch in derselben Anwendung erfolgt, müssen Sie warten.


Alle diese Entscheidungen werden natürlich vom Anwendungsentwickler getroffen. Die richtigen Entscheidungen darüber, wann dieser oder jener Ansatz angewendet werden soll, helfen dabei, das Beste aus dem Cluster herauszuholen. Es ist wichtig, dass der Entwickler auf SQL-Ebene für Verbindungen und Transaktionen zwischen ihnen wechseln kann.


Kontrolle in der Praxis


Standardmäßig bietet PostgreSQL Konsistenz. Dies wird durch den synchronous_commit gesteuert. Standardmäßig ist es aktiviert, es stehen jedoch drei weitere Optionen zur Verfügung: local , remote_write oder off .


Wenn der Parameter ausgeschaltet ist, werden alle synchronen Festschreibungen auch im lokalen System gestoppt. Der Parameter in local bestimmt den Synchronmodus für das lokale System, Schreibvorgänge in Replikate sind jedoch asynchron. Remote_write geht noch weiter: Schreibvorgänge in Replikate werden asynchron ausgeführt, aber zurückgegeben, wenn das Replikat den Datensatz akzeptiert, ihn aber nicht auf die Festplatte geschrieben hat.


In Anbetracht der verfügbaren Optionen wählen wir das Verhalten aus. Wenn wir uns daran erinnern, dass es sich um synchrone Datensätze handelt, wählen wir local für asynchrone Festschreibungen über das Netzwerk aus, während lokale Festschreibungen synchron bleiben.


Jetzt werden wir Ihnen gleich erklären, wie Sie dies konfigurieren. Stellen Sie sich jedoch vor, wir setzen synchronous_commit für den Server auf local . Wir haben uns gefragt, ob es möglich ist, den Parameter synchronous_commit laufenden Betrieb zu ändern, und es hat sich herausgestellt, dass dies nicht nur möglich ist, sondern es gibt sogar zwei Möglichkeiten, dies zu tun. Die erste besteht darin, Ihre Verbindungssitzung wie folgt einzurichten:


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

Alle nachfolgenden Datensätze in der Sitzung bestätigen die Schreibvorgänge für die Replikate, bevor ein positives Ergebnis an den verbundenen Client zurückgegeben wird. Es sei denn, Sie ändern die Einstellung synchronous_commit erneut. Sie können den SESSION Teil des Befehls weglassen, da er den Standardwert hat.


Der zweite Weg ist gut, wenn Sie nur sicherstellen möchten, dass Sie eine synchrone Replikation für eine einzelne Transaktion erhalten. In vielen NoSQL-Datenbanken existiert das Konzept von Transaktionen nicht, aber es existiert in PostgreSQL. In diesem Fall starten Sie die Transaktion und setzen synchronous_commit auf on bevor Sie in die Transaktion schreiben. COMMIT die Transaktion mit einem beliebigen Wert des zu diesem Zeitpunkt festgelegten Parameters synchronous_commit Es ist jedoch am besten, die Variable im Voraus festzulegen, um sicherzustellen, dass andere Entwickler verstehen, dass die Datensätze nicht asynchron sind.


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

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


PostgreSQL-Setup


Zuvor hatten wir uns ein PostgreSQL-System vorgestellt, bei dem synchronous_commit auf local . Um dies auf der Serverseite zu realisieren, müssen Sie zwei Serverkonfigurationsparameter festlegen. Ein weiterer synchronous_standby_names Parameter übernimmt, wenn synchronous_commit ist. Es bestimmt, welche Replikate für synchrone Commits geeignet sind, und wir setzen es auf * , was bedeutet, dass alle Replikate aktiviert sind. Diese Werte werden normalerweise in der Konfigurationsdatei konfiguriert, indem Folgendes hinzugefügt wird:


 synchronous_commit = local synchronous_standby_names='*' 

Indem Sie den Parameter synchronous_commit auf local , erstellen wir ein System, in dem lokale Laufwerke synchron bleiben, Netzwerk-Replikat-Commits jedoch standardmäßig asynchron sind. Es sei denn, wir beschließen natürlich, diese Commits wie oben gezeigt synchron zu machen.


Wenn Sie die Entwicklung des Governor-Projekts verfolgt haben , haben Sie möglicherweise einige kürzlich vorgenommene Änderungen ( 1 , 2 ) festgestellt, mit denen Governor-Benutzer diese Parameter testen und ihre Konsistenz kontrollieren konnten.


Noch ein paar Worte ...


Noch vor einer Woche würde ich Ihnen sagen, dass es nicht möglich ist, PostgreSQL so fein abzustimmen. Zu diesem Zeitpunkt bestand Kurt, ein Mitglied des Compose-Plattformteams, darauf, dass es eine solche Gelegenheit gab. Er beruhigte meine Einwände und fand Folgendes in der PostgreSQL-Dokumentation:



Dieser Parameter kann jederzeit geändert werden. Das Verhalten für jede Transaktion wird durch die Einstellung bestimmt, die beim Festschreiben wirksam wird. Daher ist es möglich und nützlich, dass Commits für einige Transaktionen synchron und für andere asynchron festgeschrieben werden. Um beispielsweise zu erzwingen, dass eine einzelne Transaktion mit mehreren Anweisungen asynchron multistatement wird, wenn der Standardwert des Parameters umgekehrt ist, setzen Sie SET LOCAL synchronous_commit TO OFF in der Transaktion auf SET LOCAL synchronous_commit TO OFF .


Mit dieser kleinen Änderung in der Konfigurationsdatei haben wir den Benutzern die Möglichkeit gegeben, ihre Konsistenz und Leistung zu steuern.

Source: https://habr.com/ru/post/de472364/


All Articles