
Das Hauptziel von Patroni ist es, High Availability für PostgreSQL zu gewährleisten. Aber Patroni ist nur eine Vorlage und kein fertiges Werkzeug (was in der Dokumentation auch gesagt wird). Auf den ersten Blick, wenn man Patroni in einer Testumgebung konfiguriert, sieht man, wie großartig dieses Werkzeug ist und wie einfach es unsere Versuche verarbeitet, den Cluster zum Absturz zu bringen. In der Praxis jedoch läuft in einer Produktionsumgebung nicht immer alles so schön und elegant wie in der Testumgebung.

Ich erzähle ein wenig über mich. Ich habe als Systemadministrator angefangen. Habe in der Webentwicklung gearbeitet. Seit 2014 arbeite ich bei Data Egret. Das Unternehmen beschäftigt sich mit Beratung im Bereich Postgres. Und wir betreuen ausschließlich Postgres und arbeiten jeden Tag mit Postgres, daher haben wir verschiedene Expertisen in Bezug auf den Betrieb.
Ende 2018 haben wir langsam angefangen, Patroni zu nutzen. Und wir haben eine bestimmte Erfahrung gesammelt. Wir haben es diagnostiziert, optimiert und sind zu unseren Best Practices gekommen. In diesem Vortrag werde ich darüber berichten.
Neben Postgres liebe ich Linux. Ich mag es, mich damit zu beschäftigen und zu forschen, ich liebe es, Kerne zu kompilieren. Ich interessiere mich für Virtualisierung, Container, Docker, Kubernetes. Das alles interessiert mich, weil alte Admin-Gewohnheiten zum Tragen kommen. Ich beschäftige mich gerne mit Überwachungssystemen. Und ich liebe postgres-bezogene Aspekte des Administrierens, wie z.B. Replikation, Datensicherung. In meiner Freizeit programmiere ich in Go. Ich bin kein Software-Ingenieur, ich programmiere nur für mich selbst in Go. Und ich finde das sehr angenehm.

- Ich denke, viele von Ihnen wissen, dass es in Postgres kein HA (High Availability) „aus der Box“ gibt. Um HA zu erhalten, muss man etwas installieren, konfigurieren, Mühe aufwenden und es verwirklichen.
- Es gibt mehrere Werkzeuge, und Patroni ist eines davon, das HA ziemlich gut und sehr effektiv löst. Aber wenn man das alles in einer Testumgebung installiert und startet, können wir sehen, dass alles funktioniert, wir können Probleme reproduzieren und beobachten, wie Patroni damit umgeht. Und wir werden sehen, dass alles wunderbar läuft.
- In der Praxis haben wir jedoch mit verschiedenen Problemen zu kämpfen gehabt. Über diese Probleme werde ich berichten.
- Ich werde erzählen, wie wir das diagnostiziert haben und welche Anpassungen wir vorgenommen haben – ob uns das geholfen hat oder nicht.

- Ich werde nicht erzählen, wie man Patroni installiert, weil man das im Internet google kann, man kann sich die Konfigurationsdateien anschauen, um zu verstehen, wie alles startet und eingestellt wird. Man kann sich in die Schemas und Architekturen einarbeiten, indem man Informationen darüber im Internet findet.
- Ich werde nicht über die Erfahrungen anderer sprechen. Ich werde nur über die Probleme berichten, mit denen wir konfrontiert waren.
- Ich werde auch nicht über Probleme sprechen, die außerhalb von Patroni und PostgreSQL liegen. Zum Beispiel werde ich nicht über Probleme mit der Lastverteilung berichten, als unser Cluster zusammenbrach.

Und eine kleine Disclaimer, bevor wir mit unserem Vortrag beginnen.
All diese Probleme, mit denen wir konfrontiert waren, traten in den ersten 6-7-8 Monaten des Betriebs auf. Im Laufe der Zeit haben wir zu unseren eigenen internen Best Practices gefunden. Und die Probleme sind verschwunden. Daher wurde der Vortrag vor etwa einem halben Jahr angekündigt, als dies alles frisch im Gedächtnis war und ich mich gut daran erinnerte.
Im Laufe der Vorbereitung des Vortrags habe ich bereits alte Postmortems durchgesehen und Protokolle betrachtet. Und einige Details könnten vergessen worden sein, oder einige Details könnten während der Problemanalyse nicht gründlich genug untersucht worden sein, weshalb es in manchen Punkten so erscheinen könnte, dass die Probleme nicht vollständig behandelt wurden oder es an Informationen mangelt. Daher bitte ich um Entschuldigung für diesen Punkt.

Was ist Patroni?
- Es ist ein Muster für den Aufbau von HA. So steht es in der Dokumentation. Und aus meiner Sicht ist das eine sehr richtige Präzisierung. Patroni ist keine silberne Kugel, die all Ihre Probleme lösen wird; man muss also Anstrengungen unternehmen, damit es funktioniert und Nutzen bringt.
- Es handelt sich um einen Agentendienst, der auf jedem Dienst mit einer Datenbank installiert wird und der gewissermaßen ein Init-System für Ihr Postgres ist. Er startet Postgres, stoppt es, setzt es neu in Gang, ändert Konfigurationen und verändert die Topologie Ihres Clusters.
- Um den Zustand des Clusters und dessen aktuelle Darstellung zu speichern, braucht man ein entsprechendes Speichersystem. In dieser Hinsicht hat Patroni den Weg eingeschlagen, den Zustand in einem externen System zu speichern. Es handelt sich um ein System zur verteilten Speicherung von Konfigurationen. Das können Etcd, Consul, ZooKeeper oder das Kubernetes-Etcd sein, also irgendeine dieser Optionen.
- Eine der Besonderheiten von Patroni ist, dass Sie den Auto-Failover direkt out-of-the-box erhalten, indem Sie ihn einfach konfigurieren. Im Vergleich zu Repmgr gibt es dort den Failover als Teil des Pakets. Mit Repmgr erhalten wir den Switchover, aber wenn wir den Auto-Failover wollen, muss er zusätzlich konfiguriert werden. Im Patroni ist der Auto-Failover bereits enthalten.
- Es gibt noch viele andere Dinge. Zum Beispiel die Verwaltung von Konfigurationen, das Hinzufügen neuer Replikate, Datensicherung usw. Aber das sind Themen, die über den Bericht hinausgehen, darüber werde ich nicht sprechen.

Ein kleines Fazit ist, dass die Hauptaufgabe von Patroni darin besteht, den Auto-Failover gut und zuverlässig zu gestalten, damit unser Cluster funktionsfähig bleibt und die Anwendung Änderungen in der Cluster-Topologie nicht wahrnimmt.

Wenn wir jedoch beginnen, Patroni zu verwenden, wird unser System etwas komplexer. Wenn wir vorher Postgres hatten, erhalten wir mit der Verwendung von Patroni Patroni selbst, wir erhalten DCS, wo der Status gespeichert wird. Und das alles muss irgendwie funktionieren. Was kann also schiefgehen?
Es kann Folgendes schiefgehen:
- Postgres kann ausfallen. Es kann sich um den Master oder die Replik handeln, eines von beiden kann ausfallen.
- Patroni selbst kann ausfallen.
- DCS, in dem der Status gespeichert wird, kann ausfallen.
- Und das Netzwerk kann ausfallen.
All diese Punkte werde ich im Bericht behandeln.

Ich werde die Fälle der Komplexität nach behandeln, nicht aus der Sicht der Komponenten, die betroffen sind, sondern aus der Sicht der subjektiven Wahrnehmung, wonach ein Fall für mich schwierig war, weil er schwer zu analysieren war… und umgekehrt, dass ein anderer Fall einfach war und leicht zu analysieren war.

Und der erste Fall ist der einfachste. Das ist der Fall, wenn wir einen Datenbankcluster genommen haben und auf demselben Cluster unser DCS-Speicher eingerichtet haben. Das ist der häufigste Fehler. Es ist ein Fehler im Design der Architektur, d. h. die Kombination verschiedener Komponenten an einem Ort.
So, es gab einen Failover, lassen Sie uns herausfinden, was passiert ist.

Hier interessiert uns der Zeitpunkt, an dem der Failover stattgefunden hat. Das heißt, uns interessiert dieser Moment, als sich der Status des Clusters ändert.
Aber ein Failover ist nicht immer ein einmaliges Ereignis, d. h. es braucht nicht immer eine bestimmte Zeitspanne, es kann sich hinziehen. Es kann über einen längeren Zeitraum andauern.
Deshalb hat er eine Start- und eine Endzeit, d. h. es handelt sich um ein fortlaufendes Ereignis. Wir teilen alle Ereignisse in drei Intervalle auf: Wir haben die Zeit vor dem Failover, während des Failovers und nach dem Failover. Das heißt, wir betrachten alle Ereignisse in diesem Zeitrahmen.

Und als erstes, als das Failover auftrat, suchen wir die Ursache, was passiert ist, was dazu führte, dass das Failover stattfand.
Wenn wir uns die Protokolle ansehen, werden wir die klassischen Protokolle von Patroni sehen. Er teilt uns mit, dass der Server zum Master geworden ist und die Rolle des Masters auf diesen Knoten übergegangen ist. Hier ist es hervorgehoben.

Als nächstes müssen wir verstehen, warum das Failover passiert ist, d. h. welche Ereignisse dazu geführt haben, dass die Rolle des Masters von einem Knoten zu einem anderen gewechselt hat. Und in diesem Fall ist alles einfach. Wir haben einen Kommunikationsfehler mit dem Speichersystem. Der Master stellte fest, dass er nicht mit dem DCS arbeiten kann, d. h. es gab ein Problem mit der Interaktion. Und er sagt, dass er nicht mehr der Master sein kann und legt seine Befugnisse nieder. Diese Zeile „demoted self“ besagt genau das.

Wenn wir uns die Ereignisse ansehen, die dem Failover vorausgingen, können wir die Gründe erkennen, die das Problem für die Fortsetzung der Arbeit des Masters verursacht haben.
Wenn wir die Protokolle von Patroni betrachten, sehen wir eine Vielzahl von Fehlern, Timeouts, d. h. der Patroni-Agent kann nicht mit dem DCS arbeiten. In diesem Fall ist es der Consul-Agent, mit dem über den Port 8500 kommuniziert wird.
Das Problem hierbei ist, dass Patroni und die Datenbank auf dem gleichen Host ausgeführt werden. Und auf demselben Knoten liefen die Consul-Server. Indem wir eine Belastung auf dem Server erzeugten, schufen wir Probleme auch für Server Consul. Sie konnten nicht richtig kommunizieren.

Nach einer gewissen Zeit, als die Last nachgelassen hatte, konnte unser Patroni wieder mit den Agenten kommunizieren. Die normale Funktion wurde wiederhergestellt. Und derselbe Server Pgdb-2 wurde erneut zum Master. Das heißt, es gab einen kurzen Flip, aufgrund dessen der Knoten seine Befugnisse als Master niederlegte und dann wieder übernahm, d. h. alles kehrte zu dem zurück, was es war.

Und das kann als Fehlalarm betrachtet werden, oder man kann argumentieren, dass Patroni alles richtig gemacht hat. Das heißt, er erkannte, dass er den Zustand des Clusters nicht aufrechterhalten kann und legte seine Befugnisse nieder.
Und hier entstand das Problem, weil die Consul-Server auf derselben Hardware wie die Datenbanken laufen. Folglich wirkt sich jede Belastung – sei es eine Belastung der Festplatten oder Prozessoren – auch auf die Interaktion mit dem Consul-Cluster aus.

Und wir haben entschieden, dass dies nicht zusammen existieren sollte, wir haben einen separaten Cluster für Consul eingerichtet. Patroni arbeitete bereits mit einem separaten Consul, das heißt, es gab einen separaten Postgres-Cluster und einen separaten Consul-Cluster. Dies ist eine grundlegende Anleitung, wie man all diese Dinge verteilt und hält, damit sie nicht zusammen existieren.
Als Option könnte man die Parameter ttl, loop_wait, retry_timeout anpassen, d. h. versuchen, durch die Erhöhung dieser Parameter diese kurzfristigen Lastspitzen zu überstehen. Aber das ist nicht die beste Lösung, denn diese Belastung kann über einen längeren Zeitraum anhalten. Und wir würden einfach über die Grenzen dieser Parameter hinausgehen. Das könnte nicht wirklich hilfreich sein.

Das erste Problem, wie Sie verstanden haben, ist einfach. Wir haben die DCS zusammen mit der Datenbank platziert und dadurch ein Problem verursacht.

Das zweite Problem ähnelt dem ersten. Es ist ähnlich, weil wir erneut Schwierigkeiten mit der Interaktion mit dem DCS-System haben.

Wenn wir die Protokolle betrachten, sehen wir, dass erneut ein Kommunikationsfehler aufgetreten ist. Und Patroni sagt, dass ich nicht mit dem DCS kommunizieren kann, weshalb der aktuelle Master in den Replikat-Modus wechselt.
Der alte Master wird zum Replikat, hier funktioniert Patroni wie vorgesehen. Er startet pg_rewind, um das Transaktionsprotokoll zurückzusetzen und sich dann mit dem neuen Master zu verbinden und ihn einzuholen. Hier funktioniert Patroni, wie es ihm zusteht.

Hier müssen wir den Ort finden, der dem File Error vorausging, also die Fehler, die der Grund dafür waren, warum der File Error aufgetreten ist. In dieser Hinsicht ist es sehr praktisch, mit den Protokollen von Patroni zu arbeiten. Er schreibt in bestimmten Intervallen dieselben Nachrichten. Und wenn wir beginnen, diese Protokolle schnell durchzugehen, sehen wir, dass sich die Protokolle geändert haben, was bedeutet, dass irgendwelche Probleme aufgetreten sind. Wir gehen schnell an diesen Ort zurück und schauen, was passiert.
In einer normalen Situation sehen die Protokolle etwa so aus. Der Besitzer der Sperre wird überprüft. Und wenn der Besitzer zum Beispiel gewechselt hat, können bestimmte Ereignisse eintreten, auf die Patroni reagieren muss. In diesem Fall ist bei uns jedoch alles in Ordnung. Wir suchen nach dem Zeitpunkt, als die Fehler auftraten.

Und wenn wir bis zu dem Punkt zurückspulen, an dem die Fehler begannen, sehen wir, dass wir einen Auto-Failer hatten. Und da unsere Fehler mit der Interaktion mit DCS verbunden waren und wir in unserem Fall Consul verwendet haben, schauen wir uns auch die Protokolle von Consul an, um zu sehen, was dort passiert ist.
Bei einer groben Übereinstimmung der Zeit des Failers mit der Zeit in den Protokollen von Consul sehen wir, dass unsere Nachbarn im Consul-Cluster zu zweifeln begannen, ob es andere Mitglieder des Consul-Clusters gibt.

Und wenn wir uns die Protokolle anderer Consul-Agenten ansehen, sehen wir ebenfalls, dass dort ein gewisser Netzwerk-Collapse stattfindet. Alle Mitglieder des Consul-Clusters zweifeln an der Existenz des anderen. Dies war der Auslöser für den Failer.
Wenn wir uns anschauen, was vor diesen Fehlern passiert ist, sehen wir verschiedene Fehler, wie z. B. Deadline, RPC fehlgeschlagen, d. h. es gibt eindeutig ein Problem bei der Interaktion der Mitglieder des Consul-Clusters.

Die einfachste Antwort ist, das Netzwerk zu reparieren. Aber es ist einfach, dies von der Tribüne aus zu sagen. Die Umstände sind jedoch so, dass der Kunde sich nicht immer leisten kann, das Netzwerk zu reparieren. Er könnte sich im Rechenzentrum befinden und möglicherweise keine Möglichkeit haben, das Netzwerk zu reparieren oder auf die Hardware Einfluss zu nehmen. Daher sind andere Optionen nötig.

Es gibt Optionen:
- Die einfachste Möglichkeit, die meines Erachtens sogar in der Dokumentation steht, besteht darin, die Consul-Überprüfungen zu deaktivieren, d. h. einfach ein leeres Array zu übergeben. Damit sagen wir dem Consul-Agenten, keine Überprüfungen durchzuführen. Durch diese Überprüfungen können wir diese Netzwerkstürme ignorieren und den Failer nicht auslösen.
- Eine andere Möglichkeit besteht darin, den raft_multiplier zu überprüfen. Dies ist ein Parameter des Consul-Servers. Standardmäßig ist er auf den Wert 5 eingestellt. Dieser Wert wird in der Dokumentation für Staging-Umgebungen empfohlen. Im Grunde beeinflusst dieser Parameter die Häufigkeit des Nachrichtenaustauschs zwischen den Mitgliedern des Consul-Netzwerks. Tatsächlich hat dieser Parameter Einfluss auf die Geschwindigkeit der Kommunikation zwischen den Mitgliedern des Consul-Clusters. Für Produktionsumgebungen wird empfohlen, ihn zu verringern, damit die Knoten häufiger Nachrichten austauschen.
- Eine andere Option, die wir begonnen haben zu nutzen, ist die Erhöhung der Priorität der Consul-Prozesse im Vergleich zu anderen Prozessen für den Prozessscheduler des Betriebssystems. Es gibt einen solchen Parameter namens „nice“, der genau die Priorität der Prozesse definiert, die der Betriebssystem-Scheduler bei der Planung berücksichtigt. Wir haben den Consul-Agenten den Wert von nice verringert, d.h. die Priorität erhöht, damit das Betriebssystem den Consul-Prozessen mehr Zeit für die Ausführung ihrer Arbeit und ihres Codes einräumt. In unserem Fall hat dies unser Problem gelöst.
- Eine andere Option ist, Consul nicht zu verwenden. Ich habe einen Kollegen, der ein großer Befürworter von Etcd ist. Und wir streiten uns regelmäßig darüber, was besser ist – Etcd oder Consul. Aber in Bezug darauf, was besser ist, sind wir uns normalerweise einig, dass Consul einen Agenten hat, der auf jedem Knoten mit der Datenbank laufen muss. Das heißt, die Interaktion von Patroni mit dem Consul-Cluster erfolgt über diesen Agenten. Und dieser Agent wird zum Engpass. Wenn mit dem Agenten etwas passiert, kann Patroni nicht mehr mit dem Consul-Cluster arbeiten. Das ist ein Problem. Bei Etcd gibt es keinen Agenten. Patroni kann direkt mit der Liste der Etcd-Server arbeiten und mit ihnen kommunizieren. Wenn Sie also in Ihrem Unternehmen Etcd verwenden, wäre Etcd wahrscheinlich die bessere Wahl als Consul. Aber bei unseren Kunden sind wir immer durch das eingeschränkt, was der Kunde gewählt und verwendet hat. Und bei unseren Kunden verwenden die meisten Consul.
- Und der letzte Punkt ist, die Werte der Parameter zu überprüfen. Wir können diese Parameter nach oben anpassen in der Hoffnung, dass unsere kurzfristigen Netzwerkprobleme kurz bleiben und nicht den Zeitraum dieser Parameter überschreiten. Auf diese Weise können wir die Aggressivität von Patroni bei der Ausführung des automatischen Failovers verringern, wenn irgendwelche Netzwerkprobleme auftreten.

Ich denke, viele, die Patroni verwenden, sind mit diesem Befehl vertraut.

Dieser Befehl zeigt den aktuellen Zustand des Clusters an. Und auf den ersten Blick könnte dieses Bild normal erscheinen. Wir haben einen Master, wir haben eine Replik, es gibt keine Replikationsverzögerung. Aber dieses Bild ist genau so lange normal, bis wir wissen, dass in diesem Cluster drei Knoten und nicht zwei sein sollten.

In diesem Zusammenhang gab es einen Auto-Failover. Und nach diesem Auto-Failover ist unsere Replikation verschwunden. Wir müssen herausfinden, warum sie verschwunden ist, und sie zurückbringen, wiederherstellen. Und wir schauen erneut in die Logs und sehen, warum wir einen Auto-Failover hatten.

In diesem Fall wurde die zweite Replikation zum Master. Hier ist alles in Ordnung.

Und wir müssen uns die Replikation anschauen, die abgebrochen ist und die nicht im Cluster ist. Wir öffnen die Patroni-Logs und sehen, dass wir beim Verbinden mit dem Cluster ein Problem in der Phase pg_rewind hatten. Um sich mit dem Cluster zu verbinden, muss das Transaktionsprotokoll zurückgedreht, das erforderliche Transaktionsprotokoll vom Master angefordert und dann der Master eingeholt werden.
In diesem Fall haben wir kein Transaktionsprotokoll und die Replikation kann nicht gestartet werden. Folglich stoppen wir PostgreSQL mit einem Fehler. Deshalb ist sie nicht im Cluster.

Wir müssen verstehen, warum sie nicht im Cluster ist und warum keine Protokolle vorhanden sind. Wir gehen zum neuen Master und sehen, was in seinen Protokollen steht. Es stellt sich heraus, dass beim pg_rewind ein Checkpoint stattfand. Und ein Teil der alten Transaktionsprotokolle wurde einfach umbenannt. Als der alte Master versuchte, sich mit dem neuen Master zu verbinden und diese Protokolle anzufordern, waren sie bereits umbenannt, sie waren einfach nicht mehr vorhanden.

Ich habe die Zeitstempel verglichen, als diese Ereignisse stattfanden. Und dort beträgt der Unterschied gerade einmal 150 Millisekunden, d.h. der Checkpoint wurde in 369 Millisekunden abgeschlossen, die WAL-Segmente wurden umbenannt. Und ungefähr 517 Millisekunden später, nach 150 Millisekunden, wurde das Rewind auf der alten Replikation gestartet. D.h. es reichten buchstäblich 150 Millisekunden aus, damit die Replikation sich nicht verbinden und laufen konnte.

Was sind die Optionen?
Anfangs haben wir Replikationsslots verwendet. Wir dachten, das wäre gut. Obwohl wir in der ersten Phase des Einsatzes die Slots deaktiviert haben. Wir hatten das Gefühl, wenn die Slots viele WAL-Segmente ansammeln, könnten wir den Master zum Absturz bringen. Er würde abstürzen. Wir haben eine Zeit lang ohne Slots gekämpft. Und haben verstanden, dass wir Slots benötigen, also haben wir die Slots zurückgebracht.
Es gibt jedoch ein Problem: Wenn der Master in die Replikation wechselt, entfernt er die Slots und dabei auch die WAL-Segmente. Um das Auftreten dieses Problems auszuschließen, haben wir den Parameter wal_keep_segments erhöht. Er beträgt standardmäßig 8 Segmente. Wir haben ihn auf 1.000 erhöht und geschaut, wie viel Speicherplatz wir haben. Und wir haben 16 Gigabyte für wal_keep_segments bereitgestellt. Das heißt, beim Wechseln haben wir in allen Knoten immer einen Puffer von 16 Gigabyte Transaktionsprotokollen.
Und zusätzlich – das ist auch für längere Wartungsarbeiten relevant. Angenommen, wir müssen eine der Replikate aktualisieren. Und wir möchten sie ausschalten. Wir müssen möglicherweise die Software aktualisieren, vielleicht das Betriebssystem, oder etwas anderes. Wenn wir die Replik abschalten, wird für diese Replik auch der Slot entfernt. Und wenn wir eine kleine Anzahl von wal_keep_segments verwenden, werden bei längerer Abwesenheit der Replik die Transaktionsprotokolle gespielt. Wir starten die Replik neu, sie fordert die Transaktionsprotokolle an, bei denen sie angehalten hat, aber auf dem Master könnten sie nicht mehr vorhanden sein. Und die Replik kann sich ebenfalls nicht verbinden. Daher halten wir einen großen Puffer von Protokollen bereit.


Wir haben eine Produktionsdatenbank. Dort laufen bereits Projekte.
Ein File-War ist aufgetreten. Wir sind hineingegangen und haben geschaut – alles in Ordnung, die Replikate sind da, es gibt keine Replikationsverzögerung. Auch keine Fehler in den Protokollen, alles in Ordnung.
Das Produktteam sagt, dass da eigentlich einige Daten vorhanden sein sollten, aber wir sehen sie nur in einer Quelle, und in der Datenbank sehen wir sie nicht. Und wir müssen herausfinden, was mit ihnen passiert ist.

Es ist klar, dass pg_rewind sie überschrieben hat. Das haben wir sofort verstanden, aber wir haben nachgesehen, was passiert ist.

In den Logs können wir immer feststellen, wann der File-War aufgetreten ist, wer Master geworden ist, und wir können feststellen, wer der alte Master war und wann er sich entscheiden wollte, Replik zu werden. Das heißt, wir benötigen diese Logs, um das Volumen der verlorenen Transaktionsprotokolle zu klären.
Unser alter Master hat sich neu gestartet. Und im Autostart war Patroni eingetragen. Patroni startete. Er hat sofort Postgres gestartet. Genau genommen, vor dem Start von Postgres und bevor er ihn als Replica gemacht hat, startete Patroni den Prozess pg_rewind. Dementsprechend hat er einen Teil der Transaktionsprotokolle gelöscht, neue heruntergeladen und sich verbunden. Hier hat Patroni großartig funktioniert, das heißt, wie es sein muss. Unser Cluster wurde wiederhergestellt. Wir hatten 3 Nodes, nach dem Failover 3 Nodes – alles läuft super.

Wir haben einen Teil der Daten verloren. Und wir müssen herausfinden, wie viel wir verloren haben. Wir suchen genau den Moment, in dem wir einen Rewind hatten. Wir können dies anhand solcher Protokolle finden. Der Rewind wurde gestartet, hat etwas gemacht und wurde beendet.

Wir müssen die Position im Transaktionsprotokoll finden, an der der alte Master angehalten hat. In diesem Fall ist das dieser Punkt hier. Und wir benötigen den zweiten Punkt, d. h. den Unterschied, wie weit der alte Master vom neuen abweicht.
Wir verwenden den normalen pg_wal_lsn_diff und vergleichen diese beiden Punkte. Und in diesem Fall erhalten wir 17 Megabyte. Ob das viel oder wenig ist, entscheidet jeder für sich selbst. Denn für manche sind 17 Megabyte wenig, für andere ist das viel und inakzeptabel. Hier bestimmt jeder individuell entsprechend den Geschäftserfordernissen.

Aber was haben wir für uns herausgefunden?
Zunächst müssen wir für uns entscheiden, ob der Autostart von Patroni nach einem Systemneustart immer erforderlich ist. Oftmals müssen wir auf den alten Master zugreifen, um zu sehen, wie weit er sich entfernt hat. Vielleicht auch die Segmente des Transaktionsprotokolls inspizieren, um zu sehen, was dort ist. Und herausfinden, ob wir diese Daten verlieren können oder ob wir den alten Master im Standalone-Modus starten müssen, um diese Daten abzurufen.
Und erst danach sollten wir die Entscheidung treffen, ob wir diese Daten verwerfen können oder ob wir sie wiederherstellen können, indem wir diesen Knoten als Replik in unser Cluster einfügen.
Darüber hinaus gibt es den Parameter „maximum_lag_on_failover“. Standardmäßig hat dieser Parameter, wenn ich mich nicht irre, einen Wert von 1 Megabyte.
Wie funktioniert das? Wenn unsere Replik bei der Replikationsverzögerung um 1 Megabyte Daten zurückliegt, nimmt diese Replik nicht an den Wahlen teil. Und wenn plötzlich ein Failover eintritt, schaut Patroni, welche Replikas zurückliegen. Wenn sie um eine große Menge an Transaktionsprotokollen zurückliegen, können sie nicht Master werden. Das ist eine sehr gute Schutzfunktion, die hilft, viele Datenverluste zu vermeiden.
Aber es gibt ein Problem, dass die Replikationsverzögerung im Patroni-Cluster und DCS in bestimmten Intervallen aktualisiert wird. Meines Erachtens beträgt der Standardwert für ttl 30 Sekunden.
Entsprechend kann es Situationen geben, in denen die Replikationsverzögerung für Replikate in DCS gleich ist, die tatsächliche Verzögerung jedoch ganz anders oder möglicherweise überhaupt nicht vorhanden ist, d. h. das Ganze ist nicht in Echtzeit. Und es reflektiert nicht immer das tatsächliche Bild. Man sollte darauf keine ausgeklügelte Logik aufbauen.
Und das Risiko von Datenverlusten bleibt immer bestehen. Im schlimmsten Fall eine Formel, im Durchschnitt eine andere. D. h. wenn wir die Implementierung von Patroni planen und einschätzen, wie viele Daten wir verlieren können, müssen wir auf diese Formeln setzen und uns ungefähr vorstellen, wie viele Daten wir verlieren könnten.
Und es gibt eine gute Nachricht. Wenn der alte Master vorangegangen ist, kann er aufgrund bestimmter Hintergrundprozesse vorangekommen sein. D. h. es gab möglicherweise einen Auto-Vakuum, der Daten geschrieben und in das Transaktionsprotokoll gespeichert hat. Und diese Daten können wir problemlos ignorieren und verlieren. Das ist kein Problem.

Und so sehen die Protokolle aus, wenn maximum_lag_on_failover festgelegt ist und ein Failover stattgefunden hat, und es notwendig ist, einen neuen Master auszuwählen. Die Replik bewertet sich selbst als unfähig, an den Wahlen teilzunehmen. Und sie lehnt die Teilnahme am Wettlauf um die Führungsposition ab. Stattdessen wartet sie darauf, dass ein neuer Master gewählt wird, um sich dann ihm anzuschließen. Dies ist eine zusätzliche Maßnahme zum Schutz vor Datenverlusten.


Hier hat unser Produktteam berichtet, dass ihr Produkt Probleme mit Postgres hat. Dabei kann man nicht auf den Master zugreifen, da er per SSH nicht erreichbar ist. Und ein Auto-Failover erfolgt auch nicht.
Dieser Host wurde zwangsweise neu gestartet. Aufgrund des Neustarts kam es zu einem Auto-Failover, obwohl man auch einen manuellen Auto-Failover hätte durchführen können, wie ich jetzt verstehe. Und nach dem Neustart schauen wir uns an, was mit dem aktuellen Master war.

Dabei wussten wir im Voraus, dass wir Probleme mit den Festplatten hatten, d. h. wir wussten bereits durch das Monitoring, wo wir nachforschen und was wir suchen mussten.

Wir haben uns in das Postgres-Protokoll eingeklinkt und angefangen, zu sehen, was dort passiert. Wir haben Commits gesehen, die dort ein bis zwei oder drei Sekunden dauern, was überhaupt nicht normal ist. Wir haben bemerkt, dass unser Auto-Vakuum sehr lange und seltsam gestartet wird. Und wir haben temporäre Dateien auf der Festplatte gesehen. D. h. das sind alles Anzeichen für Probleme mit den Festplatten.

Wir haben das System-Dmesg (das Log der Kernelmeldungen) überprüft und festgestellt, dass wir ein Problem mit einer der Festplatten haben. Das Festplattensystem stellte ein Software-RAID dar. Wir haben /proc/mdstat angesehen und gesehen, dass uns eine Festplatte fehlt. Das heißt, hier ist ein RAID aus 8 Festplatten, und uns fehlt eine. Wenn man sich die Folie genau ansieht, kann man im Output erkennen, dass uns sde fehlt. Wir haben, um es vereinfacht auszudrücken, eine Festplatte verloren. Das hat Festplattenprobleme ausgelöst, und die Anwendungen hatten ebenfalls Schwierigkeiten im Umgang mit dem Postgres-Cluster.

In diesem Fall hätte uns Patroni nicht geholfen, da Patroni nicht dafür zuständig ist, den Status des Servers oder der Festplatte zu überwachen. Wir müssen solche Situationen mit externem Monitoring verfolgen. Wir haben zu unserem externen Monitoring die Überwachung der Festplatten schnell hinzugefügt.
Und wir hatten den Gedanken - könnte uns Fencing oder ein Software-Watchdog helfen? Wir dachten, dass es in diesem Fall wenig hilfreich gewesen wäre, da Patroni während der Probleme weiterhin mit dem DCS-Cluster interagierte und keine Probleme sah. Das heißt, aus der Sicht von DCS und Patroni lief alles gut im Cluster, obwohl es tatsächlich Probleme mit der Festplatte und der Verfügbarkeit der Datenbank gab.

Meiner Meinung nach ist das eines der seltsamsten Probleme, die ich sehr lange untersucht habe; ich habe unzählige Logs gelesen, durchgearbeitet und habe es den Cluster-Simulator genannt.

Das Problem war, dass der alte Master nicht zu einer normalen Replik werden konnte, das heißt, Patroni startete ihn und zeigte, dass dieser Knoten als Replik vorhanden ist, aber gleichzeitig war er keine normale Replik. Jetzt werdet ihr sehen, warum. Ich habe das von der Problemanalyse behalten.

Und wie alles begann? Wie bei dem vorherigen Problem begann es mit Festplattensperren. Wir hatten eine bis zwei Commits pro Sekunde.

Es gab Verbindungsabbrüche, das heißt, die Clients wurden getrennt.

Es gab Sperren unterschiedlichen Schweregrades.

Und folglich war das Festplattensystem nicht sehr reaktionsschnell.

Und das mysteriöseste für mich war die eingetroffene sofortige Herunterfahranforderung. Postgres hat drei Abschaltmodi:
- Das ist 'graceful', wenn wir warten, bis sich alle Clients selbstständig abmelden.
- Es gibt 'fast', wenn wir die Clients zwingen, sich abzumelden, weil wir das Herunterfahren einleiten.
- Und sofort. In diesem Fall informiert immediate die Kunden nicht einmal darüber, dass sie sich abmelden müssen, es schaltet sich einfach ohne Vorwarnung aus. Und an alle Kunden sendet das Betriebssystem eine RST-Nachricht (TCP-Nachricht, dass die Verbindung unterbrochen ist und der Kunde nichts mehr holen kann).
Wer hat dieses Signal gesendet? Hintergrundprozesse von Postgres senden sich gegenseitig solche Signale nicht, d. h. es ist ein kill-9. Sie senden sich untereinander so etwas nicht, sie reagieren nur darauf, d. h. es ist ein Notneustart von Postgres. Ich weiß nicht, wer es gesendet hat.
Ich habe das mit dem Befehl „last“ überprüft und ich habe eine Person gesehen, die sich zusammen mit uns auf diesem Server angemeldet hat, aber ich habe mich nicht getraut, die Frage zu stellen. Möglicherweise war es kill -9. Ich hätte in den Logs kill -9 gesehen, da Postgres schreibt, dass es kill -9 akzeptiert hat, aber ich habe das nicht in den Logs gesehen.

Als ich weiter nachforschte, stellte ich fest, dass Patroni ziemlich lange keine Logs geschrieben hat – 54 Sekunden. Und wenn man die beiden Zeitstempel vergleicht, gab es hier ungefähr 54 Sekunden lang keine Nachrichten.

Und in dieser Zeit fand ein automatischer Failover statt. Patroni hat hier wieder einmal hervorragend gearbeitet. Unser alter Master war nicht verfügbar, irgendetwas passierte mit ihm. Und es begann die Wahl eines neuen Masters. Hier hat alles gut funktioniert. Unser pgsql01 wurde neuer Leader.

Wir haben eine Replik, die zum Master wurde. Und es gibt eine zweite Replik. Und mit der zweiten Replik gab es genau Probleme. Sie versuchte, sich neu zu konfigurieren. So wie ich es verstehe, wollte sie die recovery.conf ändern, Postgres neu starten und sich mit dem neuen Master verbinden. Sie meldet alle 10 Sekunden, dass sie es versucht, aber es nicht klappt.

Und während dieser Versuche kam das immediate-shutdown-Signal zum alten Master. Der Master wird neu gestartet. Und das Recovery wird ebenfalls gestoppt, weil der alte Master sich in den Neustart begibt. Das bedeutet, dass die Replik sich nicht mit ihm verbinden kann, weil er sich im Ausschaltmodus befindet.

Irgendwann hat es funktioniert, aber die Replikation wurde dabei nicht gestartet.
Ich habe nur eine Hypothese, dass in der recovery.conf die Adresse des alten Masters war. Und als der neue Master erschien, versuchte die zweite Replik weiterhin, sich mit dem alten Master zu verbinden.

Als Patroni auf der zweiten Replik startete, wurde der Knoten gestartet, konnte sich aber nicht über die Replikation verbinden. Und es entstand ein Replikationsrückstand, der ungefähr so aussah. Das heißt, alle drei Knoten waren vorhanden, aber der zweite Knoten blieb zurück.

Wenn man jedoch die Protokolle betrachtet, die aufgezeichnet wurden, konnte man sehen, dass die Replikation nicht starten kann, weil die Transaktionsprotokolle unterschiedlich sind. Die Transaktionsprotokolle, die vom Master angeboten werden und die in recovery.conf angegeben sind, passen einfach nicht zu unserem aktuellen Knoten.

Hier habe ich einen Fehler gemacht. Ich hätte kommen sollen, um mir anzusehen, was in recovery.conf steht, um meine Hypothese zu überprüfen, dass wir uns nicht mit dem richtigen Master verbinden. Aber ich hatte mich gerade erst damit beschäftigt und es kam mir nicht in den Sinn, oder ich sah, dass die Replikation zurücklag und sie neu gestartet werden musste. Ich habe das irgendwie nachlässig erledigt. Das war mein Fehler.

Nach 30 Minuten kam der Admin, d. h. ich startete Patroni auf der Replik. Ich hatte bereits auf sie verzichtet, ich dachte, ich müsste sie neu starten. Und ich dachte - ich starte Patroni neu, vielleicht funktioniert es ja. Die Wiederherstellung wurde gestartet. Und die Datenbank öffnete sich sogar, sie war bereit, Verbindungen entgegenzunehmen.

Die Replikation startete. Aber nach einer Minute fiel sie mit dem Fehler aus, dass die Transaktionsprotokolle nicht passen.

Ich dachte, ich starte es noch einmal neu. Ich startete Patroni erneut, wobei ich Postgres nicht neu startete, sondern nur Patroni neu startete, in der Hoffnung, dass es die Datenbank auf magische Weise startet.

Die Replikation startete erneut, aber die Einträge im Transaktionsprotokoll waren unterschiedlich, sie waren nicht dieselben wie bei dem vorherigen Startversuch. Die Replikation stoppte wieder. Die Fehlermeldung war bereits etwas anders und war für mich nicht besonders informativ.

Und hier kam mir der Gedanke – was wäre, wenn ich Postgres neu starte und gleichzeitig einen Checkpoint auf dem aktuellen Master mache, um den Punkt in den Transaktionsprotokollen ein kleines Stück nach vorne zu schieben, damit die Wiederherstellung von einem anderen Moment beginnt? Außerdem hatten wir noch etwas WAL-Backup.

Ich startete Patroni neu, machte ein paar Checkpoints auf dem Master, ein paar Restart-Punkte auf der Replik, als sie sich öffnete. Und das half. Ich dachte lange darüber nach, warum das half und wie es funktionierte. Und die Replik startete. Und die Replikation riss nicht mehr ab.

Dieses Problem gehört für mich zu den rätselhaftesten, über das ich immer noch nachgrüble, was da tatsächlich passiert ist.
Welche Schlussfolgerungen lassen sich hier ziehen? Patroni kann wie vorgesehen ohne Fehler funktionieren. Aber das ist keine 100 % Garantie, dass alles in Ordnung ist. Eine Replikation kann starten, kann sich jedoch im halbfunktionsfähigen Zustand befinden, und die Anwendung darf nicht mit einer solchen Replikation arbeiten, da dort alte Daten vorhanden sein könnten.
Und nach jedem Failover sollten wir immer prüfen, ob mit dem Cluster alles in Ordnung ist, d.h. ob die erforderliche Anzahl an Replikaten vorhanden ist und ob es keinen Replikationsverzug gibt.

Und während ich diese Probleme betrachte, werde ich Empfehlungen formulieren. Ich habe versucht, sie in zwei Folien zu bündeln. Wahrscheinlich hätte man alle Geschichten in zwei Folien zusammenfassen und nur darüber berichten können.

Wenn Sie Patroni verwenden, sollten Sie unbedingt über eine Überwachung verfügen. Sie sollten immer wissen, wann ein automatisches Failover stattgefunden hat, denn wenn Sie nicht wissen, dass ein automatisches Failover stattfand, kontrollieren Sie den Cluster nicht. Und das ist schlecht.
Nach jedem Failover müssen wir den Cluster immer manuell überprüfen. Wir müssen sicherstellen, dass wir immer die aktuelle Anzahl an Replikaten haben, keinen Replikationsverzug, und dass es keine Fehler in den Protokollen gibt, die mit der Streaming-Replikation, Patroni oder dem DCS-System zusammenhängen.
Die Automatisierung kann erfolgreich arbeiten, Patroni ist ein sehr gutes Werkzeug. Es kann funktionieren, aber das führt den Cluster nicht in den gewünschten Zustand. Und wenn wir darüber nicht informiert werden, werden wir Probleme bekommen.
Patroni ist keine Wunderwaffe. Wir müssen trotzdem verstehen, wie Postgres funktioniert, wie die Replikation funktioniert und wie Patroni mit Postgres arbeitet und wie die Kommunikation zwischen den Knoten gewährleistet wird. Das ist notwendig, um manuell auftretende Probleme beheben zu können.

Wie gehe ich an das Thema Diagnostik heran? Es ist so, dass wir mit verschiedenen Kunden arbeiten und niemand hat einen ELK-Stack, sodass wir in den Protokollen nachschauen müssen, indem wir 6 Konsolen und 2 Tabs öffnen. In einem Tab sind die Protokolle von Patroni für jeden Knoten, im anderen Tab sind die Protokolle von Consul oder Postgres, wenn nötig. Das Diagnostizieren ist sehr schwierig.
Welche Ansätze habe ich entwickelt? Erstens, ich schaue immer, wann das Failover stattfand. Und das ist für mich eine Art Trennlinie. Ich achte darauf, was vor dem Failover, während des Failovers und nach dem Failover passiert ist. Ein Failover hat zwei Zeitmarken: den Beginn und das Ende.
Als Nächstes schaue ich in den Logs nach den Ereignissen vor dem Failover, was dem Failover vorangegangen ist, d. h. ich suche nach den Gründen, warum das Failover stattgefunden hat.
Und das gibt mir ein Bild davon, was passiert ist und was in Zukunft getan werden kann, um ähnliche Umstände zu vermeiden (und damit ein Failover zu verhindern).
Und wohin schauen wir normalerweise? Ich schaue:
- Zuerst in die Logs von Patroni.
- Dann schaue ich mir die Logs von Postgres oder die DCS-Logs an, je nachdem, was in den Patroni-Logs gefunden wurde.
- Und auch die Systemlogs geben manchmal Aufschluss darüber, was die Ursache für das Failover war.

Wie halte ich es mit Patroni? Ich halte viel von Patroni. Meiner Meinung nach ist es das Beste, was es heute gibt. Ich kenne viele andere Produkte: Stolon, Repmgr, Pg_auto_failover, PAF. Vier Werkzeuge. Ich habe sie alle ausprobiert. Patroni hat mir am besten gefallen.
Wenn man mich fragt: "Empfehle ich Patroni?", sage ich ja, denn Patroni gefällt mir. Und ich habe das Gefühl, ich habe gelernt, wie man damit umgeht.
Wenn Sie interessiert sind zu sehen, welche anderen Probleme es mit Patroni gibt, außer den von mir genannten, können Sie immer die Seite auf GitHub besuchen. Dort gibt es viele verschiedene Geschichten und es werden viele interessante Probleme diskutiert. Letztendlich wurden einige Bugs erfasst und behoben, d. h. es ist eine interessante Lektüre.
Dort gibt es interessante Geschichten darüber, wie Menschen sich ins eigene Knie schießen. Sehr lehrreich. Man liest und versteht, dass man es so nicht machen sollte. Ich habe mir einen Haken gesetzt.
Und ich möchte dem Unternehmen Zalando ein großes Dankeschön dafür sagen, dass sie dieses Projekt vorantreiben, insbesondere Alexander Kukushkin und Alexey Klyukin. Alexey Klyukin ist einer der Mitautoren, er arbeitet nicht mehr bei Zalando, aber das sind die zwei Personen, die mit diesem Produkt begonnen haben.
Und ich halte Patroni für eine sehr coole Sache. Ich bin zufrieden, dass es existiert; es ist interessant, damit zu arbeiten. Ein großes Dankeschön an alle Mitwirkenden, die Patches für Patroni schreiben. Ich hoffe, dass Patroni mit der Zeit reifer, cooler und funktionaler wird. Es funktioniert bereits gut, aber ich hoffe, dass es noch besser wird. Wenn Sie planen, Patroni bei sich einzusetzen, dann scheuen Sie sich nicht. Es ist eine gute Lösung, die man implementieren und nutzen kann.
Das ist alles. Wenn Sie Fragen haben, stellen Sie diese bitte.

Fragen
Danke für den Vortrag! Wenn man nach dem Failover trotzdem sehr genau hinschauen muss, warum brauchen wir dann einen automatischen Failover?
Weil es etwas Neues ist. Wir arbeiten erst seit einem Jahr damit. Man sollte lieber auf Nummer sicher gehen. Wir wollen reingehen und sehen, ob wirklich alles so funktioniert hat, wie es sollte. Das ist ein gewisses Maß an Erwachsensein, das Misstrauen – besser etwas mehr zu überprüfen und nachzusehen.
Zum Beispiel sind wir am Morgen reingegangen und haben nachgeschaut, oder?
Nicht am Morgen, wir erfahren normalerweise fast sofort vom Auto-Failer. Wir bekommen Benachrichtigungen, sehen, dass der Auto-Failer passiert ist. Wir schauen fast sofort nach. Aber all diese Prüfungen sollten auf die Monitoring-Ebene übertragen werden. Wenn man zu Patroni über die REST API geht, gibt es eine Historie. Über die Historie kann man die Zeitstempel sehen, wann der Failer aufgetreten ist. Basierend darauf kann man Monitoring erstellen. Man kann die Historie betrachten, wie viele Ereignisse es gab. Wenn es mehr Ereignisse gibt, bedeutet das, dass der Auto-Failer stattgefunden hat. Man kann nachsehen. Oder unsere Automatisierung im Monitoring hat überprüft, dass alle Replikate vorhanden sind, es keine Verzögerung gibt und alles gut ist.
Danke!
Vielen Dank für die großartige Geschichte! Wenn wir den DCS-Cluster irgendwo weit vom Postgres-Cluster verlegt haben, muss dieser Cluster dann auch regelmäßig gewartet werden? Welche Best Practices gibt es dafür, dass bestimmte Teile des DCS-Clusters abgeschaltet werden, dass man etwas damit macht usw.? Wie funktioniert dabei die gesamte Struktur? Und wie macht man diese Dinge?
Für ein Unternehmen musste eine Problemmatrix erstellt werden, was passiert, wenn eines oder mehrere Komponenten ausfallen. Anhand dieser Matrix durchgehen wir nacheinander alle Komponenten und erstellen Szenarien für den Fall, dass diese Komponenten ausfallen. Für jedes Ausfallszenario kann es dann einen Aktionsplan zur Wiederherstellung geben. Und im Fall von DCS gehört das als Teil der Standardinfrastruktur dazu. Und der Administrator verwaltet dies, und wir verlassen uns bereits auf die Administratoren, die das verwalten und auf ihre Fähigkeiten, es im Falle eines Ausfalls zu reparieren. Wenn der DCS gar nicht vorhanden ist, bauen wir ihn auf, aber wir überwachen ihn dabei nicht speziell, weil wir nicht für die Infrastruktur verantwortlich sind, geben aber Empfehlungen, was und wie man monitoren sollte.
D. h. habe ich das richtig verstanden, dass man Patroni abschalten, den Failer deaktivieren und alles abstellen muss, bevor man etwas mit den Hosts macht?
Es hängt davon ab, wie viele Knoten wir im DCS-Cluster haben. Wenn es viele Knoten gibt und wir nur einen Knoten (eine Replik) außer Betrieb nehmen, bleibt das Quorum im Cluster erhalten. Und Patroni bleibt funktionsfähig. Und nichts wird ausgelöst. Wenn wir jedoch komplexe Operationen haben, die mehrere Knoten betreffen, deren Fehlen das Quorum gefährden könnte, dann ist es vielleicht sinnvoll, Patroni kurzzeitig zu pausieren. Dafür gibt es den entsprechenden Befehl – patronictl pause, patronictl resume. Wir setzen einfach auf Pause, und das automatische Failover funktioniert in dieser Zeit nicht. Wir führen Wartungsarbeiten am DCS-Cluster durch, setzen die Pause dann wieder auf und leben weiter.
Vielen Dank!
Vielen Dank für den Vortrag! Wie steht das Produktteam dazu, dass Daten verloren gehen können?
Das Produktteam ist es egal, aber die Teamleiter sind besorgt.
Welche Garantien gibt es dort?
Mit Garantien ist es sehr schwierig. Es gibt einen Vortrag von Alexander Kukushkin „Wie man RPO und RTO berechnet“, d. h. die Wiederherstellungszeit und wie viele Daten wir verlieren können. Ich denke, wir sollten diese Folien finden und sie uns ansehen. Soweit ich mich erinnere, gibt es dort konkrete Schritte, wie man diese Dinge berechnet. Wie viele Transaktionen können wir verlieren, wie viele Daten können wir verlieren. Als Möglichkeit könnten wir die synchrone Replikation auf Patroni-Ebene verwenden, aber das ist ein zweischneidiges Schwert: entweder haben wir Datensicherheit oder wir verlieren an Geschwindigkeit. Es gibt zwar synchrone Replikation, aber die garantiert auch keinen 100%-igen Schutz vor Datenverlust.
Alexey, danke für den tollen Vortrag! Gibt es Erfahrungen mit der Verwendung von Patroni für den nullten Schutzlevel? Das heißt, in Verbindung mit dem synchronen Standby? Das ist die erste Frage. Und die zweite Frage. Sie haben verschiedene Lösungen verwendet. Wir haben Repmgr verwendet, aber ohne automatisches Failover und planen jetzt, das automatische Failover zu aktivieren. Wir betrachten Patroni als alternative Lösung. Was können Sie im Vergleich zu Repmgr als Vorteile nennen?
Die erste Frage war zur synchronen Replikation. Keiner von uns verwendet synchrone Replikation, weil alle Angst haben (es verwenden bereits mehrere Kunden, Probleme mit der Leistung wurden grundsätzlich nicht festgestellt — Anmerkung des Vortragenden). Aber wir haben für uns die Regel aufgestellt, dass es im Cluster der synchronen Replikation mindestens drei Knoten geben muss, denn wenn wir zwei Knoten haben und einer der Master oder Repliken ausfällt, geht Patroni dazu über, diesen Knoten in den Standalone-Modus zu versetzen, damit die Anwendung weiterhin arbeiten kann. In diesem Fall besteht das Risiko eines Datenverlusts.
Zum zweiten Punkt haben wir Repmgr verwendet und verwenden es aus historischen Gründen immer noch bei einigen Kunden. Was kann man dazu sagen? In Patroni ist die Auto-Failover-Funktion standardmäßig integriert, bei Repmgr ist sie bereits eine zusätzliche Funktion, die aktiviert werden muss. Es ist notwendig, den Repmgr-Daemon auf jedem Knoten zu starten, und dann können wir das Auto-Failover einrichten.
Repmgr überprüft, welche Postgres-Knoten aktiv sind. Die Repmgr-Prozesse überprüfen die Existenz miteinander, was nicht sehr effizient ist, da es komplexe Fälle der Netzwerk-Isolation geben kann, in denen ein großer Repmgr-Cluster sich in mehrere kleine zerlegen und weiterarbeiten kann. Ich habe lange nicht mehr auf Repmgr geachtet, vielleicht wurde das behoben... vielleicht aber auch nicht. Aber die Auslagerung von Informationen über den Zustand des Clusters in DCS, wie es Stolon und Patroni machen, ist die lebensfähigste Option.
Alexej, ich habe eine Frage, vielleicht eine unerfahrene. In einem der ersten DCS-Beispiele hast du es von einer lokalen Maschine auf einen Remote-Knoten ausgelagert. Wir verstehen, dass ein Netzwerk eine eigene Dynamik hat. Was passiert, wenn aus irgendeinem Grund der DCS-Cluster nicht mehr verfügbar ist? Ich möchte die Gründe nicht ansprechen; es könnte viele Ursachen geben: von fehlerhaften Netzwerktechnikern bis hin zu echten Problemen.
Ich habe das nicht laut ausgesprochen, aber der DCS-Cluster sollte ebenfalls ausfallsicher sein, d. h. eine ungerade Anzahl von Knoten haben, damit ein Quorum gebildet werden kann. Was passiert, wenn der DCS-Cluster nicht mehr verfügbar ist oder kein Quorum gebildet werden kann, also bei einem Netzwerk-Split oder einem Knotenfehler? In diesem Fall wechselt der Patroni-Cluster in den Nur-Lesen-Modus. Der Patroni-Cluster kann den Zustand des Clusters und was zu tun ist, nicht bestimmen. Er kann nicht mit DCS kommunizieren und den neuen Zustand des Clusters nicht speichern, weshalb der gesamte Cluster in den Nur-Lesen-Modus wechselt. Er wartet entweder auf manuelle Eingriffe des Operators oder darauf, dass DCS wiederhergestellt wird.
Groß gesagt, wird DCS für uns zu einem Dienst, der ebenso wichtig ist wie die Datenbank selbst?
Ja, ja. In sehr vielen modernen Unternehmen ist Service Discovery ein unverzichtbarer Bestandteil der Infrastruktur. Es wird sogar früher implementiert, als eine Datenbank in der Infrastruktur vorhanden ist. Um es vereinfacht zu sagen: Die Infrastruktur wurde gestartet, das Rechenzentrum wurde eingerichtet, und sofort haben wir Service Discovery. Wenn es sich um Consul handelt, kann auch DNS darauf aufgebaut werden. Wenn es sich um Etcd handelt, kann ein Teil des Kubernetes-Clusters sein, in dem bereits alles andere bereitgestellt wird. Ich denke, dass Service Discovery bereits ein integraler Bestandteil moderner Infrastrukturen ist. Und man denkt viel früher darüber nach als über Datenbanken.
Danke!
Quelle: habr.com
