Cosa sono gli slot di replica?
Ai tempi in cui gli "slot di replica" non erano ancora stati introdotti, la gestione dei segmenti WAL era una sfida. Nella replica in streaming standard, il master non è a conoscenza dello stato dello slave. Prendi l'esempio di un master che esegue una transazione di grandi dimensioni, mentre un nodo standby è in modalità di manutenzione per un paio d'ore (come l'aggiornamento dei pacchetti di sistema, la regolazione della sicurezza della rete, l'aggiornamento dell'hardware, ecc.). Ad un certo punto, il master rimuove il registro delle transazioni (segmenti WAL) al passaggio del checkpoint. Una volta che lo schiavo è fuori manutenzione, potrebbe avere un enorme ritardo dello schiavo e deve mettersi al passo con il padrone. Alla fine, lo schiavo avrà un problema fatale come di seguito:
LOG: started streaming WAL from primary at 0/73000000 on timeline 1
FATAL: could not receive data from WAL stream: ERROR: requested WAL segment 000000010000000000000073 has already been removed
L'approccio tipico è specificare nel tuo postgresql.conf uno script di archiviazione WAL che copierà i file WAL in una o più posizioni di archivio a lungo termine. Se non disponi di standby o altri client di replica in streaming, in pratica il server può eliminare il file WAL una volta che lo script di archivio è terminato o risponde OK. Ma avrai ancora bisogno di alcuni file WAL recenti per il ripristino in caso di arresto anomalo (i dati dei file WAL recenti vengono riprodotti durante il ripristino in caso di arresto anomalo. Nel nostro esempio di un nodo standby che viene posizionato per un lungo periodo di manutenzione, sorgono problemi quando torna online e chiede il file primario per un file WAL che il primario non ha più, quindi la replica non riesce.
Questo problema è stato risolto in PostgreSQL 9.4 tramite "Slot di replica".
Se non si utilizzano gli slot di replica, un modo comune per ridurre il rischio di mancata replica è impostare wal_keep_segments sufficientemente alto in modo che i file WAL che potrebbero essere necessari non vengano ruotati o riciclati. Lo svantaggio di questo approccio è che è difficile determinare quale sia il valore migliore per la tua configurazione. Non avrai bisogno di manutenzione su base giornaliera o non dovrai conservare una grande pila di file WAL che consumano lo spazio di archiviazione del tuo disco. Sebbene funzioni, non è una soluzione ideale poiché rischiare di spazio su disco sul master può causare il fallimento delle transazioni in entrata.
Un approccio alternativo per non utilizzare gli slot di replica consiste nel configurare PostgreSQL con l'archiviazione continua e fornire un restore_command per dare alla replica l'accesso all'archivio. Per evitare l'accumulo di WAL sul primario, è possibile utilizzare un volume o un dispositivo di archiviazione separato per i file WAL, ad esempio SAN o NFS. Un'altra cosa è con la replica sincrona poiché richiede che il primario debba attendere che i nodi di standby eseguano il commit della transazione. Ciò significa che assicura che i file WAL siano stati applicati ai nodi di standby. Tuttavia, è meglio fornire i comandi di archiviazione dal primario in modo che una volta che i WAL sono stati riciclati nel primario, ti assicuri di avere backup WAL in caso di ripristino. Sebbene in alcune situazioni, la replica sincrona non sia una soluzione ideale in quanto comporta un sovraccarico delle prestazioni rispetto alla replica asincrona.
Tipi di slot di replica
Ci sono due tipi di slot di replica. Questi sono:
Slot di replica fisica
Può essere utilizzato per la replica di streaming standard. Si assicureranno che i dati non vengano riciclati troppo presto.
Slot di replica logica
La replica logica fa la stessa cosa degli slot di replica fisica e viene utilizzata per la replica logica. Tuttavia, vengono utilizzati per la decodifica logica. L'idea alla base della decodifica logica è quella di offrire agli utenti la possibilità di allegare il registro delle transazioni e decodificarlo con un plug-in. Consente di estrarre le modifiche apportate al database e quindi al log delle transazioni in qualsiasi formato e per qualsiasi scopo.
In questo blog, utilizzeremo gli slot di replica fisica e come ottenere questo risultato utilizzando ClusterControl.
Vantaggi e svantaggi dell'utilizzo degli slot di replica
Gli slot per le repliche sono decisamente utili una volta abilitati. Per impostazione predefinita, gli "Slot di replica" non sono abilitati e devono essere impostati manualmente. Tra i vantaggi dell'utilizzo degli slot di replica ci sono
- Assicura che il master conservi un numero sufficiente di segmenti WAL affinché tutte le repliche possano riceverli
- Impedisce al master di rimuovere righe che potrebbero causare conflitti di ripristino sulle repliche
- Un master può riciclare il log delle transazioni solo dopo che è stato utilizzato da tutte le repliche. Il vantaggio qui è che uno slave non può mai rimanere indietro così tanto da richiedere una nuova sincronizzazione.
Anche gli slot di replica sono dotati di alcuni avvertimenti.
- Uno slot di replica orfano può causare una crescita illimitata del disco a causa di file WAL accumulati dal master
- I nodi slave sottoposti a una lunga manutenzione (come giorni o settimane) e che sono legati a uno slot di replica avranno una crescita illimitata del disco a causa dei file WAL accumulati dal master
Puoi monitorarlo interrogando pg_replication_slots per determinare gli slot che non vengono utilizzati. Lo ricontrolleremo un po' più tardi.
Utilizzo degli slot di replica
Come affermato in precedenza, esistono due tipi di slot di replica. Per questo blog, utilizzeremo gli slot di replica fisica per la replica in streaming.
Creazione di uno slot di replica
Creare una replica è semplice. È necessario invocare la funzione esistente pg_create_physical_replication_slot per farlo e deve essere eseguita e creata nel nodo master. La funzione è semplice,
maximus_db=# \df pg_create_physical_replication_slot
Schema | pg_catalog
Name | pg_create_physical_replication_slot
Result data type | record
Argument data types | slot_name name, immediately_reserve boolean DEFAULT false, OUT slot_name name, OUT xlog_position pg_lsn
Type | normal
es. Creazione di uno slot di replica denominato slot1,
postgres=# SELECT pg_create_physical_replication_slot('slot1');
-[ RECORD 1 ]-----------------------+---------
pg_create_physical_replication_slot | (slot1,)
I nomi degli slot di replica e la relativa configurazione sottostante sono solo a livello di sistema e non a livello di cluster. Ad esempio, se si dispone di nodoA (master corrente) e nodi standby nodoB e nodoC, creando lo slot su un nodo masterA ovvero "slot1", i dati non saranno disponibili per il nodoB e il nodoC. Pertanto, quando sta per verificarsi il failover/switchover, devi ricreare gli slot che hai creato.
Eliminazione di uno slot di replica
Gli slot di replica non utilizzati devono essere eliminati o eliminati. Come affermato in precedenza, quando sono presenti slot di replica orfani o slot che non sono stati assegnati a nessun client o nodo di standby, possono causare problemi di spazio su disco illimitato se non vengono eliminati. Quindi è molto importante che questi debbano essere eliminati quando non vengono più utilizzati. Per rilasciarlo, invoca semplicemente pg_drop_replication_slot. Questa funzione ha la seguente definizione:
maximus_db=# \df pg_drop_replication_slot
Schema | pg_catalog
Name | pg_drop_replication_slot
Result data type | void
Argument data types | name
Type | normal
Lasciarlo cadere è semplice:
maximus_db=# select pg_drop_replication_slot('slot2');
-[ RECORD 1 ]------------+-
pg_drop_replication_slot |
Monitoraggio degli slot di replica PostgreSQL
Il monitoraggio dei tuoi slot di replica è qualcosa da non perdere. Raccogli semplicemente le informazioni dalla vista pg_replication_slots nel nodo primario/master proprio come di seguito:
postgres=# select * from pg_replication_slots;
-[ RECORD 1 ]-------+-----------
slot_name | main_slot
plugin |
slot_type | physical
datoid |
database |
active | t
active_pid | 16297
xmin |
catalog_xmin |
restart_lsn | 2/F4000108
confirmed_flush_lsn |
-[ RECORD 2 ]-------+-----------
slot_name | main_slot2
plugin |
slot_type | physical
datoid |
database |
active | f
active_pid |
xmin |
catalog_xmin |
restart_lsn |
confirmed_flush_lsn |
Il risultato sopra mostra che lo slot_principale è stato preso, ma non lo slot_principale2.
Un'altra cosa che puoi fare è monitorare il ritardo rispetto agli slot che hai. Per ottenere ciò, puoi semplicemente utilizzare la query basata sul risultato di esempio riportato di seguito:
postgres=# SELECT redo_lsn, slot_name,restart_lsn,
round((redo_lsn-restart_lsn) / 1024 / 1024 / 1024, 2) AS GB_behind
FROM pg_control_checkpoint(), pg_replication_slots;
redo_lsn | slot_name | restart_lsn | gb_behind
------------+-----------+-------------+-----------
1/8D400238 | slot1 | 0/9A000000 | 3.80
Ma redo_lsn non è presente in 9.6, userà redo_location, quindi in 9.6,
imbd=# SELECT redo_location, slot_name,restart_lsn,
round((redo_location-restart_lsn) / 1024 / 1024 / 1024, 2) AS GB_behind
FROM pg_control_checkpoint(), pg_replication_slots;
-[ RECORD 1 ]-+-----------
redo_location | 2/F6008BE0
slot_name | main_slot
restart_lsn | 2/F6008CC0
gb_behind | 0.00
-[ RECORD 2 ]-+-----------
redo_location | 2/F6008BE0
slot_name | main_slot2
restart_lsn | 2/F6008CC0
gb_behind | 0.00
Requisiti delle variabili di sistema
L'implementazione degli slot di replica richiede l'impostazione manuale. Ci sono variabili che devi tenere a mente che richiedono modifiche e che devono essere specificate nel tuo postgresql.conf. Vedi sotto:
- max_replication_slots – Se impostato su 0, significa che gli slot di replica sono completamente disabilitati. Se stai usando PostgreSQL <10 versioni, questo slot deve essere specificato diverso da 0 (predefinito). Da PostgreSQL 10, il valore predefinito è 10. Questa variabile specifica il numero massimo di slot di replica. L'impostazione di un valore inferiore rispetto al numero di slot di replica attualmente esistenti impedirà l'avvio del server.
- wal_level – deve essere almeno una replica o superiore (la replica è predefinita). L'impostazione di hot_standby o archivio verrà mappata sulla replica. Per uno slot di replica fisico, la replica è sufficiente. Per gli slot di replica logica, è preferibile il logico.
- max_wal_senders – impostato su 10 per impostazione predefinita, 0 nella versione 9.6, il che significa che la replica è disabilitata. Ti suggeriamo di impostarlo almeno su 16, specialmente durante l'esecuzione con ClusterControl.
- hot_standby – nelle versioni <10, è necessario impostarlo su attivo che è disattivato per impostazione predefinita. Questo è importante per i nodi in standby, il che significa che quando sono attivi puoi connetterti ed eseguire query durante il ripristino o in modalità standby.
- primary_slot_name: questa variabile viene impostata tramite recovery.conf sul nodo di standby. Questo è lo slot che deve essere utilizzato dal ricevitore o dal nodo standby durante la connessione con il mittente (o primario/master).
Devi notare che queste variabili richiedono principalmente un riavvio del servizio database per ricaricare nuovi valori.
Utilizzo degli slot di replica in un ambiente ClusterControl PostgreSQL
Ora, vediamo come possiamo utilizzare gli slot di replica fisica e implementarli all'interno di una configurazione Postgres gestita da ClusterControl.
Distribuzione di nodi di database PostgreSQL
Iniziamo a distribuire un cluster PostgreSQL a 3 nodi utilizzando ClusterControl utilizzando la versione PostgreSQL 9.6 questa volta.
ClusterControl distribuirà nodi con le seguenti variabili di sistema definite di conseguenza in base alle loro impostazioni predefinite o regolato i valori. In:
postgres=# select name, setting from pg_settings where name in ('max_replication_slots', 'wal_level', 'max_wal_senders', 'hot_standby');
name | setting
-----------------------+---------
hot_standby | on
max_replication_slots | 0
max_wal_senders | 16
wal_level | replica
(4 rows)
Nelle versioni PostgreSQL> 9.6, il valore predefinito di max_replication_slots è 10 che è abilitato per impostazione predefinita ma non nelle versioni 9.6 o precedenti che è disabilitato per impostazione predefinita. Devi assegnare max_replication_slots maggiori di 0. In questo esempio, ho impostato max_replication_slots su 5.
[email protected]:~# grep 'max_replication_slots' /etc/postgresql/9.6/main/postgresql.conf
# max_replication_slots = 0 # max number of replication slots
max_replication_slots = 5
e riavviato il servizio,
[email protected]:~# pg_lsclusters
Ver Cluster Port Status Owner Data directory Log file
9.6 main 5432 online postgres /var/lib/postgresql/9.6/main pg_log/postgresql-%Y-%m-%d_%H%M%S.log
[email protected]:~# pg_ctlcluster 9.6 main restart
Impostazione degli slot di replica per i nodi primari e di standby
Non c'è alcuna opzione in ClusterControl per farlo, quindi devi creare i tuoi slot manualmente. In questo esempio, ho creato gli slot nel primario nell'host 192.168.30.100:
192.168.10.100:5432 [email protected]_db=# SELECT pg_create_physical_replication_slot('slot1'), pg_create_physical_replication_slot('slot2');
pg_create_physical_replication_slot | pg_create_physical_replication_slot
-------------------------------------+-------------------------------------
(slot1,) | (slot2,)
(1 row)
Controllare ciò che abbiamo appena creato mostra,
192.168.10.100:5432 [email protected]_db=# select * from pg_replication_slots;
slot_name | plugin | slot_type | datoid | database | active | active_pid | xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn
-----------+--------+-----------+--------+----------+--------+------------+------+--------------+-------------+---------------------
slot1 | | physical | | | f | | | | |
slot2 | | physical | | | f | | | | |
(2 rows)
Ora nei nodi standby, dobbiamo aggiornare recovery.conf e aggiungere la variabile primary_slot_name e cambiare application_name in modo che sia più facile identificare il nodo. Ecco come appare nell'host 192.168.30.110 recovery.conf:
[email protected]:/var/lib/postgresql/9.6/main/pg_log# cat ../recovery.conf
standby_mode = 'on'
primary_conninfo = 'application_name=node11 host=192.168.30.100 port=5432 user=cmon_replication password=m8rLmZxyn23Lc2Rk'
recovery_target_timeline = 'latest'
primary_slot_name = 'slot1'
trigger_file = '/tmp/failover_5432.trigger'
Fai la stessa cosa anche nell'host 192.168.30.120 ma cambia il nome_applicazione e imposta primary_slot_name ='slot2'.
Controllo dell'integrità dello slot di replica:
192.168.10.100:5432 [email protected]_db=# select * from pg_replication_slots;
slot_name | plugin | slot_type | datoid | database | active | active_pid | xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn
-----------+--------+-----------+--------+----------+--------+------------+------+--------------+-------------+---------------------
slot1 | | physical | | | t | 24252 | | | 0/CF0A4218 |
slot2 | | physical | | | t | 11635 | | | 0/CF0A4218 |
(2 rows)
Cos'altro ti serve?
Poiché ClusterControl non supporta gli slot di replica a partire da questo momento, è necessario tenere in considerazione alcuni aspetti. Cosa sono questi? Entriamo nei dettagli.
Processo di failover/commutazione
Quando è stato tentato un failover automatico o un passaggio tramite ClusterControl, gli slot non verranno mantenuti dai nodi primari e di standby. Devi ricrearlo manualmente, controllare le variabili se impostate correttamente e modificare recovery.conf di conseguenza.
Ricostruire uno schiavo da un padrone
Quando si ricostruisce uno slave, recovery.conf non verrà mantenuto. Ciò significa che le impostazioni di recovery.conf con nome_slot_primario verranno cancellate. Devi specificarlo di nuovo manualmente e controllare la vista pg_replication_slots per determinare se gli slot sono stati utilizzati correttamente o sono rimasti orfani.
Se vuoi ricostruire il nodo slave/standby da un master, potresti dover considerare di specificare la variabile env PGAPPNAME proprio come il comando seguente:
$ export PGAPPNAME="app_repl_testnode15"; /usr/pgsql-9.6/bin/pg_basebackup -h 192.168.10.190 -U cmon_replication -D /var/lib/pgsql/9.6/data -p5434 -W -S main_slot -X s -R -P
Specificare il parametro -R è molto importante, quindi ricreerà recovery.conf, mentre -S specificherà quale nome di slot utilizzare durante la ricostruzione del nodo di standby.
Conclusione
L'implementazione degli slot di replica in PostgreSQL è semplice, ma ci sono alcuni avvertimenti che devi ricordare. Durante la distribuzione con ClusterControl, dovrai aggiornare alcune impostazioni durante il failover o le ricostruzioni slave.