Einrichtung der synchronen Replikation für Hochverfügbarkeit in PostgreSQL

Erfahren Sie, wie Sie eine PostgreSQL-Hochverfügbarkeit mit null Datenverlust (RPO=0) mithilfe synchroner Streaming-Replikation konfigurieren. Dieses Schritt-für-Schritt-Tutorial behandelt die wesentlichen Konfigurationen für `wal_level`, Replikations-Slots, `pg_basebackup` und die korrekte Einstellung der `synchronous_commit`-Parameter auf dem primären und den Standby-Servern, um die Transaktionsbeständigkeit in kritischen Umgebungen zu gewährleisten.

42 Aufrufe

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)). Wenn N=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 in synchronous_standby_names auf 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 Datei standby.signal und generiert die notwendigen Verbindungseinstellungen in postgresql.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_write oder on erhöht die Transaktionslatenz im Vergleich zu asynchronen Modi (off oder local) 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_error vertraut. Wenn diese auf off gesetzt 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.