Re: PostgreSQL Cluster
Andreas Kretschmer <[email protected]> Fri, 11 May 2018 09:46:14 +0200
| Newsgroups | gmane.comp.db.postgresql.german |
|---|---|
| Message-ID | <[email protected]> |
Moin, Am 10.05.2018 um 11:11 schrieb Andreas Kretschmer: > On 10 May 2018 10:27:51 CEST, Michael Post <[email protected]> wrote: >> Hallo, >> >> ich versuche einen PostgreSQL-Cluster mit aktuell zwei Nodes >> aufzubauen. >> Ziel ist es, eine ausfallsichere Umgebung aufzubauen, so dass >> theoretisch jederzeit ein Node wegbrechen kann und die Umgebung dennoch >> korrekt weiterläuft (auch ohne Eingriff eines Administrators). >> Gleichzeitig ist ein Loadbalancing über alle verfügbare Nodes >> gewünscht. >> >> Ich habe mich mit pgpool2 beschäftigt. Aber irgendwie ist mir das >> Prinzip noch nicht ganz klar, wie die Nodes synchron gehalten werden >> und >> wie ein zuvor weggebrochender Node wieder mit dem vorher existierenden >> Node synchronisiert wird (evtl. automatisch?). >> >> Ich baue eine komplett neue Umgebung damit auf und kann daher gleich >> auf >> PostgreSQL 10 aufsetzen. >> >> Habt Ihr einen Hinweis oder eine gute Doku für mich, die auf PostgreSQL >> 10 aufsetzt und mich an das Thema besser einführt? >> >> Vielen Dank für Eure Unterstützung, >> >> Michael > Ich antworte dir morgen ausführlich ;-) Du willst einen Cluster, wo jeder Knoten stets die gleichen Daten hat. Dazu bietet sich Replikation an. Vor PostgreSQL 9.0 gab es keine eingebaute Replikation, was dazu führte, daß es verschiedene Ansätze (externe Lösungen) gab, dies zu realisieren. so gab (und gibt es) TRIGGER-basierte Lösungen (Slony, Londiste, ...) die bei z.B. einem INSERT dafür sorgten, daß dieser Datensatz auch in einer weiteren DB eingetragen wurde. Nachteil: erhöhter Aufwand auf dem Master (TRIGGER sind 'teuer'), allerdings gibt es auch einen Vorteil: das funktioniert auch versionsübergreifend. Andere Lösung: man schaltet eine Instanz davor, die, wenn sie eine schreibende Operation erkennt, diese auf 2 oder mehr der angeschlossenen Instanzen ausführt. Bestes Beispiel dafür ist pgpool2. Nachteil: diese Instanz davor muß jede ankommende Query erst einmal selber zerlegen und prüfen, was diese macht. Bei einem INSERT ist das noch trivial, bei Funktionen aber nicht mehr. Insbesondere dann, wenn man selber Stored Procedures schreibt. Ein "Select * from my_function(10,100)" macht genau was? Richtig, ohne diese Funktion zu kennen kann man das nicht sagen. Vor genau diesem Problem steht auch pgpool2. Seit PostgreSQL 9.0 gibt es die eingebaute "Streaming Replication" (SR). Diese sorgt für ein binärgleiches Abbild des Masters auf den Standbys. Dazu werden alle physischen Änderungen (das Transaktionslog) zu dem oder den Standbys übertragen. Vorteil: (nahezu) keine extra Belastung auf dem Master, Nachteil: geht nicht versionsübergreifend. Mit dieser Streaming Replication sind eigentlich die anderen Lösungen obsolet, weil die Vorteile von SR überwiegen. Nachteil ist, daß es nicht möglich ist, nur einen Teilset der DB zu replizieren und daß es nicht möglich ist, das versionsübergreifend zu replizieren. Um diese Nachteile noch zu lösen, hat insbesondere (aber nicht nur) ein Team von 2ndQuadrant die physische Replikation von SR (es werden quasi physische Diffs von Binärdateien übertragen) zu einer logischen Replikation erweitert. Dazu wird dieser Stream von physischen Diffs wieder in logische SQL-Befehle übersetzt. Vorteil: damit ist es sowohl möglich, nur definierte Teile der Gesamtdatenbank zu replizieren als auch versionsübergreifend zu replizieren. Dazu kommt noch, daß die DB, in die repliziert wird, weiter schreibbar ist. Von dieser logischen Replikation gibt es 3 grundlegende Realisierungen: * logical replication: eingebaut in PG 10. Diese erlaubt z.B. die Replikation von Tabellen, allerdings keine Filterung (auswahl der zu replizierenden Datensätze) und auch kein Konflikthandling. Eigene Befehle wie z.B. CREATE PUBLICATION, CREATE SUBSCRIPTION etc. https://www.postgresql.org/docs/10/static/logical-replication.html * pglogical: extra Modul, verfügbar ab PG 9.4. mehr Funktionen als logical replication in PG10, aber nicht im Kern der DB, daher alle Aufrufen via Function Calls, z.B. pglogical.create_subscription(), siehe https://www.2ndquadrant.com/en/resources/pglogical/pglogical-docs/ * BDR: Bi-Directional Replication. Das ist eine volle Multi-Master-Lösung, für wohl maximal 48 gleichzeitige aktive Master. Ideal für geographisch weit verteilte Systeme, wir haben Kunden mit BDR und Servern in Amerika, Europa und Asien und eben volle Multi-Master-Replikation dazwischen. BDR Version 1 ist weiter unter Support, aber keine neuen Features mehr. Version2 und Version 3(derzeit Beta, ab Ende Mai wohl verfügbar) sind die aktiv in Entwicklung befindlichen Versionen. Was Du brauchst bzw. suchst ist offenbar eine Master-Standby-Lösung mittels SR. Die Applikation schreibt alle Änderungen in den Master (A) und kann die Daten auch auf dem Standby (S) lesen. Falls der Master ausfällt, sollen die Zugriffe auf den Standby gehen und dieser auch zum Master promotet werden. (man muß noch zwischen synchroner und asynchroner Replikation unterscheiden) Zum Aufsetzen einer solchen Replikation empfehlen wir ein Tool, was wir auch dafür entwickelt haben: repmgr https://repmgr.org/ . Wenn das korrekt eingerichtet ist, kannst Du via "repmgr standby switchover" z.B. für eine geplante Wartung am Master die Rollen Master <-> Standby einfach tauschen. Das ist aber noch keine HA, kein automatisches Failover. Dazu kann man on top von repmgr noch den passenden Deamon nutzen, den repmgrd. Dieser überwacht von dem/den Standby(s) den Master und sorgt bei dessen Ausfall für das automatische Promoten eines Standbys. Was noch fehlt: wie erfährt das die Applikation? Dafür gibt es, Du ahnst es, wieder verschiedene Möglichkeiten. JDBC-basierte Applikationen können das im JDBC-Treiber einstellen, dieser hat ein eingebautes Auto-Failover. Dazu nennt man in connection-string alle Server (Master und alle Standbys) und gibt an, was man haben will: den Master oder 'nur' einen Standby. PostgreSQL 10 hat dies nun in der libpq auch. Damit kannst Du also in der Applikation sagen: es gibt server1, server2, server3 - bitte suche mir den aktuellen Master und verbinde Dich damit. Damit hast allerdings noch keine Lastvrteilung, Du landest IMMER auf dem Master. Ist Deine Applikation schlau genug zu wissen, daß die folgenden Abfragen alle nur rein lesend sind, könnte diese auch eine weitere Verbindung zur DB aufbauen und dabei angeben, daß ein ReadOnly-Server, also Standby, ausreicht. Ein Wort noch zu pgpool2: dieses kann einfaches connection-pooling, aber auch Verteilung schreibender Zugriffe auf mehrere Knoten. Das brauchst Du aber bei SR nicht wirklich. Was bleibt, ist, daß pgpool2 relativ viel Code ist und relativ aufwendig ist, für etwas, was man eigentlich nicht braucht. Ein connection-pooler kann aber dennoch durchaus sinnvoll sein. Die von uns dafür unterstützte Lösung ist pgbouncer. So, ich hoffe, nun bist Du völlig verunsichert und brauchst eine weitergehende Beratung von uns ;-) tl;dr * nehmt PG10 * nutzt die eingebaute SR * schaut Euch repmgr an https://repmgr.org/ * prüft, wie sich die Applikation verbindet (libpq, JDBC) und nutzt dessen Features für Autofailover * schaut Euch noch Barman an https://www.pgbarman.org/index.html um auch eine gute Lösung für Backup zu haben * repmgr und Barman sind von uns entwickelt und werden natürlich durch uns supportet, sind aber frei nutzbar * falls ihr einen 24*7*365-Support braucht, fragt uns (bzw. mich) Falls ihr der Meinung seid, ihr braucht BDR: Version 1 ist frei verfügbar, würde ich aber nicht (mehr) empfehlen. Versionen 2 und 3 benötigen einen Supportvertrag mit uns. Kein Schnäppchen, aber erstklassig und auch wirklich sinnvoll. Wir entdecken durch BDR z.B. immer mal wieder Bugs direkt im PG-Core, und wer BDR einsetzt hat dazu auch eine kritische Anwendung und braucht dazu auch den Support von uns. Natürlich finanzieren wir auch die weitere Entwicklung von BDR durch solche Supportverträge. Andreas -- 2ndQuadrant - The PostgreSQL Support Company. www.2ndQuadrant.com