Postgres viene fornito con funzionalità di replica fisica e logica. Continua a leggere per saperne di più sui vari aspetti della replica fisica.
Replica fisica
I metodi di replica fisica vengono utilizzati per mantenere una copia completa dell'intero dato di un singolo cluster (in Postgres, un cluster è un insieme di database gestiti da un singolo processo del server Postgres principale chiamato postmaster ), tipicamente su un'altra macchina. La macchina di origine è chiamata primaria nel gergo di Postgres, e la destinazione si chiama standby .
Standby caldo, caldo e "freddo"
Un server standby che viene mantenuto il più aggiornato possibile con il primario in tempo reale e consente ai client di eseguire transazioni di sola lettura è chiamato hot standby, o più comunemente una replica di lettura . Gli hot standby sono stati aggiunti a Postgres nella versione 9, prima della quale c'erano solo caldi standby. Un warmstandby è simile a un hot standby, tranne per il fatto che non consente ai client di connettersi ad esso.
(A parte:gli hot standby non possono eseguire query che creano tabelle temporanee. Questa è una limitazione di Postgres.)
Uno standby "freddo" (non un termine ufficiale) è solitamente un server standby che non si avvia fino a un failover. Poiché il cold standby non è attivo e funzionante, è possibile che all'avvio debba prima applicare le modifiche in sospeso prima di poter iniziare ad accettare le connessioni client.
File WAL
Nel normale corso delle operazioni, un server PostgreSQL genera una serie ordinata di record WAL (write ahead log). Questi sono fondamentalmente un registro delle modifiche, simile all'AOF di Redis o al binlog di MySQL. Al centro, la replica fisica è il trasporto di questi record su un'altra macchina e il fatto che l'altro postmaster che è in esecuzione lì accetti e applichi questi record nel suo database locale.
I record WAL sono suddivisi in file di dimensioni uguali (in genere 16 MB) chiamati segmenti WAL o semplicemente file WAL . Questi file vengono creati in una directory chiamata pg_wal
nella directory dei dati del cluster (pg_wal
è stato chiamato pg_xlog
nelle versioni di Postgres precedenti alla 10). I vecchi file WAL vengono eliminati quando non sono più necessari (e anche in base a un paio di parametri di configurazione).
Modalità di ripristino
Il postmaster può essere avviato in una modalità chiamata modalità di ripristino , inserendo un file di configurazione valido chiamato recovery.conf nella directory dei dati del cluster. In modalità di ripristino, Postgres importerà e applicherà solo file WAL generati dal server primario e di per sé non genererà alcun file WAL. I server warm e hotstandby vengono eseguiti in modalità di ripristino.
Una volta avviato in modalità di ripristino, Postgres proverà prima a importare tutti i file WAL disponibili in un archivio (più di questo sotto). Quando l'archivio non ha più file WAL da offrire, prova a importare tutti i file che si trovano intorno a pg_wal
di init directory. Quando anche quelle sono terminate, se una connessione primaria è configurata e modalità_attesa impostata su on
in recovery.conf, Postgres si collegherà al primario e tirerà e applicherà i nuovi record WAL man mano che vengono creati nel primario.
Spedizione log
Immagina di avere un trigger che verrà invocato sul server primario ogni volta che viene creato un nuovo file WAL. Questo trigger può quindi copiare il nuovo file WAL su un'altra macchina usando ad esempio rsync
e inseriscilo nel pg_wal
directory di un postmaster in esecuzione in modalità di ripristino. Riesci a fare uno standby come questo?
La risposta è sì, e in effetti questa era la pratica standard prima dell'aggiunta della replica in streaming in Postgres v9. Questa pratica è chiamata spedizione log .
Il trigger è uno script di shell, che può essere configurato utilizzando archive_command. Il nome e il percorso del file WAL possono essere passati allo script.
Archiviazione WAL
Invece di sincronizzare il file WAL, supponiamo di copiarlo in un bucket S3 o in una directory montata su NFS che è accessibile anche dalla macchina in standby. Questa posizione condivisa ora conterrà tutti i file WAL generati dal primario. Questo ora diventa un archivio e il processo di memorizzazione dei file WAL nell'archivio è denominato archiviazione continua o semplicemente archiviazione WAL .
L'inverso di questa operazione - il recupero dei file WAL dall'archivio in modalità arecovery Postgres - può essere configurato utilizzandorestore_command.Simile a archive_command
, anche questo è il percorso di uno script di shell. Il postmaster in esecuzione in modalità di ripristino sa quale file WAL desidera. Il nome del file può essere passato allo script.
Ad esempio, ecco i comandi di archiviazione e ripristino per l'archiviazione e il recupero di file WAL da e verso un bucket S3:
archive_command = 's3cmd put %p s3://BUCKET/path/%f' # in postgresql.conf
restore_command = 's3cmd get s3://BUCKET/path/%f %p' # in recovery.conf
All'avvio in modalità di ripristino, se restore_command
è configurato, Postgres proverà prima a recuperare i file WAL dall'archivio.
pg_standby
In modalità di ripristino, Postgres non sa e non può sapere in anticipo quanti file WAL sono stati generati finora. Se restore_command è configurato, Postgres lo invocherà ripetutamente con nomi di file WAL progressivi (i nomi sono in sequenza prevedibile) finché il comando non restituisce un errore.
Ad esempio, il comando di ripristino è stato in grado di soddisfare le richieste di file WAL000000010000000000000001
tramite 00000001000000000000001A
ma non riesce per00000001000000000000001B
poiché non è stato trovato nella posizione dell'archivio. In assenza di file WAL da altre fonti, Postgres presumerà che il file WAL 00000001000000000000001B
deve ancora essere generato dal ripristino primario e terminerà dopo aver applicato 00000001000000000000001A
.
Considera cosa succede se il comando di ripristino attende il file00000001000000000000001B
essere disponibile, piuttosto che uscire con un errore poiché non è stato trovato. Postgres continuerà ad attendere il comando di ripristino e, pertanto, continuerà ad essere in modalità di ripristino.
Questa è una configurazione valida e un modo valido per configurare un warm standby.
Postgres viene fornito con un comando chiamatopg_standby, che può essere utilizzato per impostare un warm standby in questo modo, purché l'archivio sia una directory.pg_standby
attenderà che un file diventi disponibile, se non può essere trovato.
I comandi di archiviazione e ripristino utilizzando pg_standby saranno simili a questo:
archive_command = 'cp %p /some/path/%f' # in postgresql.conf
restore_command = 'pg_standby /some/path %f %p' # in recovery.conf
Replica in streaming
Dopo l'elaborazione dei file WAL archiviati e dei file nel pg_wal
directory, Postgres può connettersi a un server primario sulla rete e recuperare ripetutamente e applicare nuovi file WAL man mano che vengono creati. Questa funzionalità, aggiunta in Postgres 9, è chiamata replica in streaming .
Il server primario a cui connettersi può essere specificato nel file recovery.conf:
# recovery.conf
standby_mode = on
primary_conninfo = 'host=10.0.1.10 user=repl password=p@ssw0rd'
Hot Standby
Per impostazione predefinita, quando è in modalità di ripristino, Postgres non accetterà le connessioni client, rifiutandole con messaggi di errore "il sistema di database è in modalità di ripristino". Aggiungendo la riga hot_standby = on
in recovery.conf, puoi stabilire connessioni client Postgresaccept e consentire loro di eseguire transazioni di sola lettura:
# recovery.conf
hot_standby = on
Di solito non c'è motivo per disattivare hot_standby.
I documenti PostgreSQL contengono maggiori informazioni sulla configurazione e l'esecuzione di uno standby in modalità "hot standby".
Slot di replica
Gli slot di replica sono stati introdotti in Postgres 9.4. Sono un meccanismo per tenere traccia in modo accurato e duraturo di quanto uno standby è in ritardo rispetto al primario. Ciò consente al primario di garantire che i file WAL ancora necessari per il recupero dello standby non vengano eliminati.
Prima degli slot di replica, non era possibile per il primario determinarlo e finivi in situazioni in cui uno standby veniva lasciato bloccato perché un file WAL di cui aveva bisogno era stato eliminato dal primario. Naturalmente, gli archivi WAL possono risolvere questo problema. Senza un archivio WAL, tuttavia, l'unica opzione era ricostruire lo standby da un nuovo backup.
Puoi leggere ulteriori informazioni sulla replica slot qui.
Passaggi per configurare un Hot Standby
Diamo un'occhiata ai passaggi necessari per configurare un hot standby per un primario esistente.
Innanzitutto, abbiamo bisogno di un utente per la connessione in standby come:
$ psql -p 6000
psql (11.2 (Debian 11.2-1.pgdg90+1))
Type "help" for help.
postgres=# CREATE USER repluser REPLICATION PASSWORD 'p@ssw0rd';
CREATE USER
E le modifiche corrispondenti in pg_hba.conf
:
# TYPE DATABASE USER ADDRESS METHOD
host replication repluser standby-ip/32 md5
# (replace standby-ip)
Ovviamente puoi usare qualsiasi meccanismo di autenticazione standard di PostgreSQL. L'utente deve disporre dei privilegi di replica e di accesso e non richiede l'accesso a un database specifico.
Assicurati di ricaricare il server primario affinché le modifiche a pg_hba.conf abbiano effetto.
Lo standby deve iniziare da un backup del primario. Puoi e dovresti farlo usando pg_basebackup
con un nuovo slot di replica:
pg_basebackup -h primary-ip -p 6000 -U repluser -C -S slot_standby1 -R -D standby
Questo si collega al primario su primary-ip:6000
con l'utente che abbiamo appena creato e ne fa un backup nella directory standby
. Un nuovo slot di replicaslot_standby1
viene creato.
Utilizzeremo questo slot come slot di replica in standby, in modo che ci sia continuità dal backup.
Avevamo chiesto pg_basebackup
per creare un recovery.conf
per noi sopra (opzione “-R”). Diamo un'occhiata a questo:
$ cat standby/recovery.conf
standby_mode = 'on'
primary_conninfo = 'user=repluser password=''p@ssw0rd'' host=primary-ip port=6000 sslmode=prefer sslcompression=0 krbsrvname=postgres target_session_attrs=any'
primary_slot_name = 'slot_standby1'
In realtà è abbastanza buono e non è necessario modificarlo ulteriormente. Ora apriamo semplicemente lo standby:
o$ pg_ctl -D standby -l log_standby -o --port=6001 start
waiting for server to start.... done
server started
postgres@stg1:/tmp/demo$ cat log_standby
2019-06-19 09:17:50.032 UTC [21733] LOG: listening on IPv4 address "127.0.0.1", port 6001
2019-06-19 09:17:50.034 UTC [21733] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.6001"
2019-06-19 09:17:50.067 UTC [21734] LOG: database system was interrupted; last known up at 2019-06-19 09:12:05 UTC
2019-06-19 09:17:50.111 UTC [21734] LOG: entering standby mode
2019-06-19 09:17:50.119 UTC [21734] LOG: redo starts at 0/2000028
2019-06-19 09:17:50.120 UTC [21734] LOG: consistent recovery state reached at 0/20000F8
2019-06-19 09:17:50.120 UTC [21733] LOG: database system is ready to accept read only connections
2019-06-19 09:17:50.138 UTC [21739] LOG: started streaming WAL from primary at 0/3000000 on timeline 1
E questo è tutto! Il file di registro indica che la replica in streaming è attiva e in esecuzione. Ora dovresti essere in grado di connetterti allo standby sulla porta 6001, eseguire query di sola lettura e vedere le modifiche replicate dal primario più o meno in tempo reale.
Passaggi successivi
I documenti PostgreSQL sono un ottimo punto di partenza per iniziare a scavare ulteriormente in tutte le funzionalità relative alla replica di Postgres. Ti consigliamo di esaminare argomenti come la replica ritardata, la replica a cascata, gli standby sincroni e altro ancora.
Sebbene Postgres sia dotato di una serie impressionante di funzionalità, ci sono ancora casi d'uso che non sono supportati. Questa pagina wiki di Postgres contiene un elenco di strumenti di terze parti che forniscono funzionalità aggiuntive relative alla replica.