PostgreSQL Hochverfügbarkeit / Skalierbarkeit mit HAProxy und PGBouncer


17

Ich habe mehrere PostgreSQL-Server für eine Webanwendung. In der Regel ein Master und mehrere Slaves im Hot-Standby-Modus (asynchrone Streaming-Replikation).

Ich verwende PGBouncer für das Verbindungs-Pooling: eine Instanz, die auf jedem PG-Server (Port 6432) installiert ist und eine Verbindung zur Datenbank auf localhost herstellt. Ich verwende den Transaktionspoolmodus.

Um meine schreibgeschützten Verbindungen auf Slaves auszugleichen, verwende ich HAProxy (v1.5) mit einer Konfiguration, die ungefähr so ​​aussieht:

listen pgsql_pool 0.0.0.0:10001
        mode tcp
        option pgsql-check user ha
        balance roundrobin
        server master 10.0.0.1:6432 check backup
        server slave1 10.0.0.2:6432 check
        server slave2 10.0.0.3:6432 check
        server slave3 10.0.0.4:6432 check

Meine Webanwendung stellt also eine Verbindung zu Haproxy (Port 10001) her, das die Verbindungen auf mehreren pgbouncern ausgleicht, die auf jedem PG-Slave konfiguriert sind.

Hier ist ein Repräsentationsdiagramm meiner aktuellen Architektur:

haproxy> pgbouncer> postgresql

Das funktioniert ganz gut so, aber ich stelle fest, dass einige dies ganz anders implementieren: Die Webanwendung stellt eine Verbindung zu einer einzelnen PGBouncer-Instanz her, die eine Verbindung zu HAproxy herstellt und die Last über mehrere PG-Server ausgleicht:

pgbouncer> haproxy> postgresql

Was ist der beste Ansatz? Der erste (mein aktueller) oder der zweite? Gibt es Vorteile einer Lösung gegenüber der anderen?

Vielen Dank

Antworten:


10

Ihre bestehende Konfiguration von HAProxy -> PGBouncer -> PGServer Ansatz ist besser. Und das funktioniert nur. Hier ist der Grund: HAProxy leitet die Verbindung zu verschiedenen Servern um. Dies führt zu einer Änderung der MAC-Adresse in der Datenbankverbindung. Befindet sich PGBouncer über HAProxy, werden die Verbindungen im Pool jedes Mal ungültig, wenn sich die MAC-Adresse ändert.


7

pgbouncer unterhält Verbindungen in einem Pool mit einem Postgres-Server. In einer Umgebung mit hohem Datenvolumen sind die Zeiten für den TCP-Verbindungsaufbau erheblich.

Clients, die eine große Anzahl von DB-Anfragen stellen, müssen für jede Anfrage eine Verbindung mit einem entfernten PGBouncer herstellen. Dies ist teurer als die lokale Ausführung von PgBouncer (daher stellt die Anwendung eine lokale Verbindung zu pgbouncer her), und pgBouncer unterhält einen Pool von Verbindungen mit dem entfernten PG-Server.

Also, IMO, PGBouncer -> HAProxy -> PGServer scheint besser zu sein als HAProxy -> PGBouncer -> PGServer, besonders wenn der PGBouncer lokal für die Client-Anwendung ist.


1

Ich muss der Antwort von donatello nicht zustimmen.

Sie sehen, wenn Ihre Anwendung DB-Verbindungen nicht über einen lokalen Pool verwaltet, erstellt sie jedes Mal eine neue Verbindung, wenn sie die DB abfragen muss. Das passiert genau so, wenn Sie PgBouncer verwenden. Sie werden also eine sehr gute Verbesserung erzielen, wenn Sie PgBouncer verwenden.

Wenn PgBouncer PostgreSQL-Verbindungen durch Pooling verwaltet, sinkt die Zeit, die Ihre App für das Öffnen einer Verbindung benötigt, im Vergleich zu der Zeit, in der die Verbindung direkt zur Datenbank geöffnet wird, erheblich. Das liegt daran, dass PG die Anmeldeinformationen und alles andere bei jeder Verbindungsanforderung nur sehr langsam überprüft und überprüft.

Daher ist der Ansatz App -> HAProxy -> [PgBouncer -> PostgreSQL] der bessere, da PgBouncer die Verbindungszeit zu PG spart. Der Pooling-Modus ist ebenfalls zu berücksichtigen. Sie müssen wissen, wie sich Ihre App verhält. Handelt es sich hauptsächlich um Transaktionen? Oder besteht es eher darin, eine Reihe kleiner SQL-Sätze mit einer hohen Nebenläufigkeit auszuführen? Alle diese Parameter wirken sich auf die Leistung aus.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.