Configurazione della Replica Sincrona per l'Alta Affidabilità in PostgreSQL
Configurare PostgreSQL per l'alta affidabilità (HA) è fondamentale per qualsiasi applicazione mission-critical. Sebbene la replica asincrona offra vantaggi in termini di prestazioni, essa comporta intrinsecamente un rischio di perdita di dati se il server primario fallisce prima che le modifiche siano completamente trasmesse allo standby. La replica in streaming sincrona risolve questo problema garantendo che una transazione sia considerata commessa solo dopo che i dati sono stati scritti con successo nel WAL (Write-Ahead Log) sia del primario sia di almeno un server standby designato. Ciò assicura un Recovery Point Objective (RPO) pari a zero.
Questa guida completa illustra i passaggi di configurazione essenziali necessari per stabilire una configurazione di replica PostgreSQL robusta e a zero perdita di dati. Ci concentreremo sui parametri critici come wal_level e synchronous_commit che sono alla base di questa architettura di alta affidabilità.
Prerequisiti
Prima di iniziare, assicurati di avere configurati due server PostgreSQL (Primario e Standby) che eseguono versioni principali identiche di PostgreSQL. Entrambi i server devono avere connettività di rete. Per questa guida, assumiamo:
- Nome host/IP Primario:
pg_primary - Nome host/IP Standby:
pg_standby - Utente di Replica:
repl_user(creato con i permessi appropriati) - Nome Database:
mydb
Fase 1: Configurazione del Server Primario
Il server primario richiede impostazioni specifiche per abilitare la replica in streaming e gestire il Write-Ahead Log (WAL) richiesto dai commit sincroni.
A. Modifica di postgresql.conf sul Primario
Modifica il file postgresql.conf del server primario. I seguenti parametri sono obbligatori per la replica in streaming:
# --- Richiesto per la Replica ---
listen_addresses = '*' # Permette connessioni dallo standby
wal_level = replica # Deve essere 'replica' o superiore (es. 'logical')
max_wal_senders = 10 # Max connessioni concorrenti dagli standby
max_replication_slots = 10 # Slot necessari per flussi di replica persistenti
# --- Essenziale per il Commit Sincrono ---
synchronous_standby_names = '1 (standby_app_name)' # Specifica gli standby richiesti
# --- Opzionale ma Raccomandato ---
wal_log_hints = on # Raccomandato per una replica più sicura, anche se aumenta il volume WAL
shared_preload_libraries = 'pg_stat_statements' # Se si utilizza il monitoraggio
Spiegazione dei Parametri Chiave:
wal_level = replica: Questo assicura che siano scritte informazioni sufficienti nel WAL per consentire a un server standby di ricostruire lo stato del database. Per i commit sincroni, questo livello è il requisito minimo.synchronous_standby_names: Questa è l'impostazione fondamentale per definire quali standby devono confermare le scritture. La definiamo utilizzando la sintassi(N (nome_standby)). SeN=1, almeno uno standby deve confermare la scrittura prima che la transazione venga commessa.
B. Configurazione dell'Autenticazione Basata su Host (pg_hba.conf)
Il server primario deve consentire all'utente di replica proveniente dal server/i standby di connettersi ai fini della replica.
Aggiungi una voce a pg_hba.conf sul primario:
# TIPO DATABASE UTENTE INDIRIZZO METODO
host replication repl_user pg_standby/32 scram-sha-256
Sostituisci pg_standby/32 con l'indirizzo IP o la subnet effettivi del tuo server standby.
C. Creazione dello Slot di Replica e dell'Utente
Connettiti a PostgreSQL sul server primario per creare l'utente e lo slot di replica necessari.
1. Crea Utente di Replica:
CREATE ROLE repl_user WITH REPLICATION LOGIN PASSWORD 'una_password_forte';
2. Crea Slot di Replica:
Questo slot assicura che i segmenti WAL vengano conservati fino a quando lo standby non conferma la ricezione, prevenendo la perdita di dati se lo standby si disconnette temporaneamente.
SELECT pg_create_physical_replication_slot('standby_app_name');
- Nota sulla Denominazione: Il nome fornito qui (
standby_app_name) deve corrispondere al nome specificato insynchronous_standby_namessul primario.
D. Riavvio del Primario
Applica tutte le modifiche alla configurazione riavviando il servizio PostgreSQL sul server primario.
sudo systemctl restart postgresql
Fase 2: Configurazione del Server Standby
Il server standby è configurato per trasmettere in streaming i record WAL dal primario utilizzando una configurazione di ripristino.
A. Backup Base
Prima di avviare lo streaming, lo standby necessita di una copia completa della directory dei dati del primario. Ferma prima PostgreSQL sullo standby.
sudo systemctl stop postgresql
Esegui il backup base utilizzando pg_basebackup. Sostituisci percorsi e dettagli di connessione come necessario:
# Esempio che utilizza l'utility pg_basebackup
pg_basebackup -h pg_primary -D /var/lib/postgresql/15/main/ -U repl_user -P -Xs -R -W
-D: La directory dei dati di destinazione sullo standby.-U: L'utente di replica.-P: Mostra il progresso.-Xs: Include i file WAL necessari durante il backup base.-R: Crea automaticamente il filestandby.signale genera le impostazioni di connessione necessarie inpostgresql.auto.conf(o configurazione di ripristino).
B. Configurazione di postgresql.conf sullo Standby
Sullo standby, assicurati che postgresql.conf gli consenta di agire come replica. L'impostazione chiave qui è l'impostazione del nome dell'applicazione, che deve corrispondere al nome dello slot utilizzato sul primario.
# --- Richiesto sullo Standby ---
primary_conninfo = 'host=pg_primary port=5432 user=repl_user password=una_password_forte application_name=standby_app_name'
hot_standby = on # Permette query di lettura durante la modalità di recupero/standby
C. Avvio dello Standby
Avvia il servizio PostgreSQL sul server standby.
sudo systemctl start postgresql
Fase 3: Verifica e Test del Commit Sincrono
Una volta che entrambi i server sono in esecuzione, verifica la connessione e poi testa il comportamento sincrono.
A. Verifica dello Stato della Replica
Connettiti al database primario e controlla la vista pg_stat_replication:
SELECT client_addr, application_name, state, sync_state FROM pg_stat_replication;
Dovresti vedere una voce per standby_app_name con sync_state impostato su sync.
B. Test del Commit Sincrono
Il parametro globale che determina quanto strettamente PostgreSQL attende è synchronous_commit. Per RPO=0, devi utilizzare un valore che forzi la sincronizzazione.
1. Impostazione del Comportamento Globale
Se hai configurato synchronous_standby_names sul primario come mostrato nella Fase 1, il comportamento predefinito imporrà l'attesa per gli standby richiesti se synchronous_commit è impostato su on (il valore predefinito) o remote_write.
Per la garanzia più forte, impostalo esplicitamente in postgresql.conf su remote_write o remote_apply (se hai bisogno che lo standby abbia scaricato i dati su disco, non solo che li abbia ricevuti).
# In postgresql.conf sul Primario
synchronous_commit = remote_write
Avviso: Impostare
synchronous_commit = remote_writeoonaumenta significativamente la latenza delle transazioni rispetto alle modalità asincrone (offolocal). Questa latenza è direttamente correlata alla velocità di rete tra il primario e lo standby sincrono.
2. Test all'Interno di una Transazione
Per testare a livello transazionale (senza richiedere una modifica della configurazione globale), è possibile impostarlo per sessione o transazione:
-- Connettiti al Primario
BEGIN;
SET LOCAL synchronous_commit = remote_write;
INSERT INTO sales (item, amount) VALUES ('Widget A', 100);
-- Questo INSERT sarà bloccato finché 'standby_app_name' non conferma la ricezione.
COMMIT;
-- Il COMMIT ha successo solo dopo che lo standby ha riconosciuto la scrittura WAL.
Se la connessione allo standby sincrono viene persa durante la transazione, il primario attenderà indefinitamente (se lo standby si disconnette correttamente) o ripiegherà in base all'impostazione synchronous_commit_fallback_on_error (che per impostazione predefinita è on, il che significa che la transazione potrebbe fallire o bloccarsi se il primario non riesce a confermare lo stato di sincronizzazione).
Best Practice per HA Sincrona
- Utilizza Standby Dedicati: Assegna alla lista di replica sincrona solo gli standby fisicamente vicini (bassa latenza) al primario. L'alta latenza influenzerà gravemente le prestazioni di scrittura.
- Monitora il Lag di Replica: Anche in modalità sincrona, monitora il lag dello standby. Uno standby lento che è ancora tecnicamente 'sync' ma impiega troppo tempo per elaborare il WAL può comunque influire sull'esperienza utente.
- Fallback della Connessione: Comprendi l'impostazione
synchronous_commit_fallback_on_error. Se impostata suoff, un fallimento nella comunicazione con lo standby sincrono durante un commit causerà il fallimento della transazione sul primario, prevenendo una potenziale divergenza dei dati, ma impattando immediatamente sulla disponibilità. - Utilizza Più Standby: Per la massima ridondanza all'interno di una configurazione sincrona, configura
synchronous_standby_names = '2 (standby1, standby2)'per richiedere commit da due standby distinti.