PostgreSQL Replication
Replication
La réplication sur PostgreSQL est un bordel. Je note donc ici pour les prochaines fois
Creation
Users
Pour créer une réplication PostgreSQL, il y a plusieurs choses à savoir
Tout d'abord, nous devons créer un utilisateur dédié pour exécuter la réplication (sur le nœud master) :
psql -c "CREATE USER replicator WITH REPLICATION ENCRYPTED PASSWORD 'Iej7choobeinohJa8shieNg4iev5dien'"
Ensuite, nous devons configurer pg_hba.conf
pour autoriser la connexion à cet utilisateur (172.29.49.11
est notre IP de secours) :
Puis on reload la configuration
Configuration
C'est la partie délicate, quelques paramètres à adapter en fonction de votre workload :
- max_wal_senders : Nombre de processus d'expéditeur WAL qui peuvent être démarrés sur le maître. Un pour chaque réplique. pg_basebackup peut utiliser un ou deux WAL senders.
max_wal_senders
est généralement fixé par défaut à 10 sur toutes les distributions. Ainsi, ce paramètre n'a pas besoin d'être modifié, sauf si nous configurons plus de 5 standby pour un maître.
- listen_addresses : Ce paramètre détermine les interfaces IP par lesquelles les connexions sont autorisées. Par défaut, il s'agit de localhost. Il peut être défini sur l'interface IP publique ou privée ou par tout en utilisant (*).
- archive_mode : Ce paramètre doit être défini sur 'ON' pour activer l'archivage. Lorsque l'archivage est activé, les segments WAL sont copiés vers l'emplacement d'archivage, avant d'être recyclés (archive_mode n'est pas un paramètre obligatoire mais suggéré pour les bases de données de production).
- archive_command : La commande shell ou un script à l'aide duquel l'archiveur doit effectuer l'archivage d'un segment WAL complet. Voici un exemple de configuration qui utilise la commande cp sous linux. Par exemple
- → %p est substitué par postgres avec le chemin d'accès au segment WAL réel.
-
→ %f est substitué par postgres avec le nom du fichier WAL.
-
wal_keep_size : Quantité de segments WAL qui doivent être au moins conservés dans le répertoire pg_wal avant d'être recyclés.
→ Comme certaines de nos bases de données sont énormes, n'hésitez pas à mettre des valeurs très élevées (comme 300GB).
Une fois que toutes ces valeurs sont correctement éditées, recharger une autre fois.
Et enfin, sur le noeud standby, nous exécutons une sauvegarde de base pour activer la réplication.
/usr/lib/postgresql/13/bin/ --create-slot --slot=data_slot_slave1 --host=172.19.49.11 --user=replicator --write-recovery-conf --wal-method=stream --pgdata=/data/pgsql/13/data/ --progress --checkpoint=fast"
Deletion
C'est la seule tâche facile dans PostgreSQL, nous devons seulement supprimer le slot de réplication.
postgres=# SELECT pg_drop_replication_slot(slot_name) FROM pg_replication_slots WHERE slot_name = 'data_slot_slave1';
C'est une commande personnalisée, elle n'échoue pas dans le cas où le slot n'existe pas. C'est utile si vous le scriptez !
Troubleshooting
Master Node
Pour troubleshoot une réplication, quelques commandes utiles :
postgres=# SELECT * FROM pg_replication_slots;
-[ RECORD 1 ]-------+---------------
slot_name | data_slot_s1
plugin |
slot_type | physical
datoid |
database |
temporary | f
active | t
active_pid | 93620
xmin | 390443541
catalog_xmin |
restart_lsn | 24A8E/76E161C8
confirmed_flush_lsn |
wal_status | reserved
safe_wal_size | 274879913528
Nous voyons ici que notre data_slot_s1
est dans wal_status
réservé et est actif, donc nous avons une réplication saine.
Pour rappel, voici ce que dit la documentation
Disponibilité des fichiers WAL revendiqués par ce slot. Les valeurs possibles sont :
reserved
signifie que les fichiers réclamés sont dans la limite de la taillemax_wal_size
.extended
signifie que la taillemax_wal_size
est dépassée mais que les fichiers sont toujours conservés, soit par le slot de réplication, soit parwal_keep_size
.unreserved
signifie que le slot ne conserve plus les fichiers WAL requis et que certains d'entre eux doivent être supprimés au prochain checkpoint. Cet état peut revenir àreserved
ouextended
.lost
signifie que certains fichiers WAL requis ont été supprimés et que ce slot n'est plus utilisable.
postgres=# select usename,application_name,client_addr,backend_start,state,sync_state from pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
usename | replicator
application_name | walreceiver
client_addr | 172.29.49.11
backend_start | 2022-11-30 23:13:43.810803+01
state | streaming
sync_state | async
Nous voyons ici que nous avons une réplication en tant que user replicator avec le serveur ayant comme IP 172.29.49.11
. Il s'agit d'une réplication ayant débuté le 30 novembre à 23:13
.
Standby Node
postgres=# select pg_is_in_recovery(),pg_is_wal_replay_paused(), pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn(), pg_last_xact_replay_timestamp();
-[ RECORD 1 ]-----------------+------------------------------
pg_is_in_recovery | t
pg_is_wal_replay_paused | f
pg_last_wal_receive_lsn | 24A8E/9DBBBE48
pg_last_wal_replay_lsn | 24A8E/9DBBBE48
pg_last_xact_replay_timestamp | 2022-12-01 11:46:05.427305+01
Nous voyons actuellement que le noeud client est en mode de récupération, et qu'il n'est pas "en pause" de réplication. Il lit actuellement le dernier segment qu'il a reçu, qui est le segment du 1er décembre à 11h45.
Si pg_last_wal_receive_lsn
et pg_last_wal_replay_lsn
étaient différents. Nous pourrions déterminer combien de Go manquent au nœud de secours, par exemple :
postgres=# select pg_wal_lsn_diff('0/925D7E70','0/2705BDA0');
-[ RECORD 1 ]---+-----------
pg_wal_lsn_diff | 1800913104
Lets see how much is 1800913104
postgres=# select round(1800913104/pow(1024,3.0),2) missing_lsn_GiB;
missing_lsn_gib
-----------------
1.68
Il manque 1,68GB sur le noeud standby, ce qui peut être beaucoup, selon la taille de votre base de données.
postgres=# SELECT CASE WHEN pg_last_wal_receive_lsn() = pg_last_wal_replay_lsn()
postgres-# THEN 0
postgres-# ELSE EXTRACT (EPOCH FROM now() - pg_last_xact_replay_timestamp())
postgres-# END AS log_delay;
-[ RECORD 1 ]
log_delay | 0
Bonne nouvelle, notre réplication est saine et n'a pas de retard !
postgres=# SELECT * FROM pg_stat_wal_receiver;
-[ RECORD 1 ]---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
pid | 211574
status | streaming
receive_start_lsn | 249B0/EC000000
receive_start_tli | 1
written_lsn | 24A8F/2AEAA10
flushed_lsn | 24A8F/2AEAA10
received_tli | 1
last_msg_send_time | 2022-12-01 12:03:26.367879+01
last_msg_receipt_time | 2022-12-01 12:03:26.382725+01
latest_end_lsn | 24A8F/2AEAA10
latest_end_time | 2022-12-01 12:03:26.367879+01
slot_name | data_slot_s1
sender_host | 172.19.49.11
sender_port | 5432
conninfo | user=replicator passfile=/var/lib/postgresql/.pgpass channel_binding=prefer dbname=replication host=172.19.49.11 port=5432 fallback_application_name=walreceiver sslmode=prefer sslcompression=0 sslsni=1 ssl_min_protocol_version=TLSv1.2 gssencmode=prefer krbsrvname=postgres target_session_attrs=any
Autres informations utiles