Einrichtung der synchronen Replikation für Hochverfügbarkeit in PostgreSQL
Die Konfiguration von PostgreSQL für Hochverfügbarkeit (HA) ist für jede geschäftskritische Anwendung von entscheidender Bedeutung. Während die asynchrone Replikation Leistungsvorteile bietet, birgt sie zwangsläufig das Risiko von Datenverlusten, falls der primäre Server ausfällt, bevor Änderungen vollständig auf den Standby-Server übertragen wurden. Die synchrone Streaming-Replikation löst dieses Problem, indem sie garantiert, dass eine Transaktion nur dann als abgeschlossen gilt, wenn die Daten erfolgreich in das WAL (Write-Ahead Log) sowohl des Primärservers als auch mindestens eines benannten Standby-Servers geschrieben wurden. Dies gewährleistet ein Recovery Point Objective (RPO) von Null.
Dieser umfassende Leitfaden führt Sie durch die notwendigen Konfigurationsschritte, um eine robuste PostgreSQL-Replikation ohne Datenverlust einzurichten. Wir konzentrieren uns auf kritische Parameter wie wal_level und synchronous_commit, die dieser Hochverfügbarkeitsarchitektur zugrunde liegen.
Voraussetzungen
Stellen Sie vor Beginn sicher, dass Sie zwei PostgreSQL-Server eingerichtet haben (Primär und Standby), die identische Hauptversionen von PostgreSQL ausführen. Beide Server müssen über Netzwerkverbindungen verfügen. Für diesen Leitfaden gehen wir von Folgendem aus:
- Primärer Hostname/IP:
pg_primary - Standby-Hostname/IP:
pg_standby - Replikationsbenutzer:
repl_user(erstellt mit den entsprechenden Berechtigungen) - Datenbankname:
mydb
Schritt 1: Konfiguration des Primärservers
Der Primärserver erfordert spezifische Einstellungen, um das Streaming der Replikation zu aktivieren und das Write-Ahead Log (WAL) zu verwalten, das für synchrone Commits erforderlich ist.
A. Anpassen von postgresql.conf auf dem Primärserver
Bearbeiten Sie die Datei postgresql.conf des Primärservers. Die folgenden Parameter sind für die Streaming-Replikation zwingend erforderlich:
# --- Erforderlich für Replikation ---
listen_addresses = '*' # Ermöglicht Verbindungen vom Standby
wal_level = replica # Muss 'replica' oder höher sein (z. B. 'logical')
max_wal_senders = 10 # Max. gleichzeitige Verbindungen von Standbys
max_replication_slots = 10 # Slots, die für persistente Replikationsstreams benötigt werden
# --- Wesentlich für Synchronous Commit ---
synchronous_standby_names = '1 (standby_app_name)' # Gibt erforderliche Standbys an
# --- Optional, aber empfohlen ---
wal_log_hints = on # Empfohlen für sicherere Replikation, obwohl es das WAL-Volumen erhöht
shared_preload_libraries = 'pg_stat_statements' # Falls Überwachung verwendet wird
Erklärung der Schlüsselparameter:
wal_level = replica: Stellt sicher, dass genügend Informationen in das WAL geschrieben werden, damit ein Standby-Server den Datenbankzustand rekonstruieren kann. Für synchrone Commits ist dies die Mindestanforderung.synchronous_standby_names: Dies ist die Kerneinstellung zur Definition, welche Standbys Schreibvorgänge bestätigen müssen. Wir definieren dies mithilfe der Syntax(N (standby_name)). WennN=1, muss mindestens ein Standby die Schreibbestätigung geben, bevor die Transaktion abgeschlossen wird.
B. Konfigurieren der hostbasierten Authentifizierung (pg_hba.conf)
Der Primärserver muss dem Replikationsbenutzer von dem/den Standby-Server(n) die Verbindung zu Replikationszwecken erlauben.
Fügen Sie dem pg_hba.conf auf dem Primärserver einen Eintrag hinzu:
# TYPE DATABASE USER ADDRESS METHOD
host replication repl_user pg_standby/32 scram-sha-256
Ersetzen Sie pg_standby/32 durch die tatsächliche IP-Adresse oder das Subnetz Ihres Standby-Servers.
C. Erstellen des Replikationsslots und des Benutzers
Stellen Sie eine Verbindung zum PostgreSQL auf dem Primärserver her, um den notwendigen Benutzer und den Replikationsslot zu erstellen.
1. Replikationsbenutzer erstellen:
CREATE ROLE repl_user WITH REPLICATION LOGIN PASSWORD 'a_strong_password';
2. Replikationsslot erstellen:
Dieser Slot stellt sicher, dass WAL-Segmente zurückgehalten werden, bis der Standby den Empfang bestätigt hat, wodurch Datenverlust verhindert wird, falls der Standby vorübergehend die Verbindung trennt.
SELECT pg_create_physical_replication_slot('standby_app_name');
- Hinweis zur Benennung: Der hier angegebene Name (
standby_app_name) muss mit dem Namen übereinstimmen, der insynchronous_standby_namesauf dem Primärserver angegeben ist.
D. Neustart des Primärservers
Übernehmen Sie alle Konfigurationsänderungen, indem Sie den PostgreSQL-Dienst auf dem Primärserver neu starten.
sudo systemctl restart postgresql
Schritt 2: Konfiguration des Standby-Servers
Der Standby-Server wird so konfiguriert, dass er WAL-Datensätze vom Primärserver über eine Wiederherstellungskonfiguration streamt.
A. Basis-Backup
Bevor das Streaming beginnt, benötigt der Standby eine vollständige Kopie des Datenverzeichnisses des Primärservers. Stoppen Sie zuerst PostgreSQL auf dem Standby.
sudo systemctl stop postgresql
Nehmen Sie das Basis-Backup mit pg_basebackup auf. Ersetzen Sie Pfade und Verbindungsinformationen nach Bedarf:
# Beispiel mit dem pg_basebackup-Dienstprogramm
pg_basebackup -h pg_primary -D /var/lib/postgresql/15/main/ -U repl_user -P -Xs -R -W
-D: Das Ziel-Datenverzeichnis auf dem Standby.-U: Der Replikationsbenutzer.-P: Fortschritt anzeigen.-Xs: Notwendige WAL-Dateien während des Basis-Backups einschließen.-R: Erstellt automatisch die Dateistandby.signalund generiert die notwendigen Verbindungseinstellungen inpostgresql.auto.conf(oder der Wiederherstellungskonfiguration).
B. Konfiguration von postgresql.conf auf dem Standby
Stellen Sie auf dem Standby sicher, dass postgresql.conf ihm erlaubt, als Replikat zu fungieren. Die Schlüsseleinstellung hier ist die Festlegung des Anwendungsnamens, der mit dem auf dem Primärserver verwendeten Slot-Namen übereinstimmen muss.
# --- Erforderlich auf dem Standby ---
primary_conninfo = 'host=pg_primary port=5432 user=repl_user password=a_strong_password application_name=standby_app_name'
hot_standby = on # Ermöglicht Leseabfragen während der Wiederherstellungs-/Standby-Modus
C. Starten des Standby-Servers
Starten Sie den PostgreSQL-Dienst auf dem Standby-Server.
sudo systemctl start postgresql
Schritt 3: Überprüfung und Test des Synchronous Commit
Sobald beide Server laufen, überprüfen Sie die Verbindung und testen Sie dann das synchrone Verhalten.
A. Überprüfung des Replikationsstatus
Stellen Sie eine Verbindung zur Primär-Datenbank her und überprüfen Sie die Ansicht pg_stat_replication:
SELECT client_addr, application_name, state, sync_state FROM pg_stat_replication;
Sie sollten einen Eintrag für standby_app_name mit sync_state als sync sehen.
B. Testen des Synchronous Commit
Der globale Parameter, der bestimmt, wie stark PostgreSQL wartet, ist synchronous_commit. Für RPO=0 müssen Sie einen Wert verwenden, der die Synchronisierung erzwingt.
1. Festlegen des globalen Verhaltens
Wenn Sie synchronous_standby_names auf dem Primärserver wie in Schritt 1 gezeigt konfiguriert haben, erzwingt das Standardverhalten das Warten auf die erforderlichen Standbys, wenn synchronous_commit auf on (Standard) oder remote_write gesetzt ist.
Für die stärkste Garantie setzen Sie es explizit in postgresql.conf auf remote_write oder remote_apply (falls der Standby die Daten auf die Festplatte geschrieben haben muss, nicht nur empfangen).
# In postgresql.conf auf dem Primärserver
synchronous_commit = remote_write
Warnung: Das Setzen von
synchronous_commit = remote_writeoderonerhöht die Transaktionslatenz im Vergleich zu asynchronen Modi (offoderlocal) erheblich. Diese Latenz korreliert direkt mit der Netzwerkgeschwindigkeit zwischen dem Primärserver und dem synchronen Standby.
2. Testen innerhalb einer Transaktion
Um transaktional zu testen (ohne eine globale Konfigurationsänderung zu erfordern), können Sie dies pro Sitzung oder Transaktion festlegen:
-- Verbindung zum Primärserver herstellen
BEGIN;
SET LOCAL synchronous_commit = remote_write;
INSERT INTO sales (item, amount) VALUES ('Widget A', 100);
-- Dieses INSERT blockiert, bis 'standby_app_name' den Empfang bestätigt hat.
COMMIT;
-- Der COMMIT wird nur erfolgreich, nachdem der Standby das WAL-Schreiben bestätigt hat.
Wenn die Verbindung zum synchronen Standby während der Transaktion unterbrochen wird, wartet der Primärserver entweder unbegrenzt (wenn der Standby sauber getrennt wird) oder fällt basierend auf der Einstellung synchronous_commit_fallback_on_error zurück (Standardeinstellung ist on, was bedeutet, dass die Transaktion fehlschlagen oder hängen bleiben kann, wenn der Primärserver den Synchronisationsstatus nicht bestätigen kann).
Best Practices für synchrone HA
- Dedizierte Standbys verwenden: Nehmen Sie nur Standbys in Ihre synchrone Replikationsliste auf, die physisch nah (geringe Latenz) am Primärserver liegen. Eine hohe Latenz beeinträchtigt die Schreibleistung erheblich.
- Replikationsverzögerung überwachen: Auch im synchronen Modus sollten Sie die Standby-Verzögerung überwachen. Ein langsamer Standby, der technisch gesehen noch 'sync' ist, aber zu lange braucht, um WAL zu verarbeiten, kann die Benutzererfahrung dennoch beeinträchtigen.
- Verbindungsfallback: Machen Sie sich mit der Einstellung
synchronous_commit_fallback_on_errorvertraut. Wenn diese aufoffgesetzt ist, führt ein Fehler bei der Kommunikation mit dem synchronen Standby während eines Commits dazu, dass die Transaktion auf dem Primärserver fehlschlägt, wodurch eine potenzielle Datenabweichung verhindert wird, dies jedoch sofort die Verfügbarkeit beeinträchtigt. - Mehrere Standbys verwenden: Für maximale Redundanz innerhalb einer synchronen Einrichtung konfigurieren Sie
synchronous_standby_names = '2 (standby1, standby2)', um Commits von zwei unterschiedlichen Standbys zu erfordern.