PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Utilisation des slots de réplication PostgreSQL

Que sont les emplacements de réplication ?

À l'époque où les "emplacements de réplication" n'étaient pas encore introduits, la gestion des segments WAL était un défi. Dans la réplication en continu standard, le maître n'a aucune connaissance de l'état de l'esclave. Prenons l'exemple d'un maître qui exécute une transaction importante, tandis qu'un nœud de secours est en mode maintenance pendant quelques heures (comme la mise à niveau des packages système, l'ajustement de la sécurité du réseau, la mise à niveau du matériel, etc.). À un moment donné, le maître supprime son journal des transactions (segments WAL) lors du passage du point de contrôle. Une fois que l'esclave est hors maintenance, il peut avoir un énorme retard d'esclave et doit rattraper le maître. Finalement, l'esclave obtiendra un problème fatal comme ci-dessous :

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'approche typique consiste à spécifier dans votre postgresql.conf un script d'archivage WAL qui copiera les fichiers WAL vers un ou plusieurs emplacements d'archivage à long terme. Si vous n'avez pas de serveurs de secours ou d'autres clients de réplication en continu, le serveur peut fondamentalement supprimer le fichier WAL une fois que le script d'archivage est terminé ou répond OK. Mais vous aurez toujours besoin de fichiers WAL récents pour la récupération après un crash (les données des fichiers WAL récents sont relues pendant la récupération après un crash. Dans notre exemple d'un nœud de secours placé pour une longue période de maintenance, des problèmes surviennent lorsqu'il revient en ligne et demande le primaire pour un fichier WAL que le primaire n'a plus, alors la réplication échoue.

Ce problème a été résolu dans PostgreSQL 9.4 via "Replication Slots".

Si vous n'utilisez pas de slots de réplication, un moyen courant de réduire le risque d'échec de la réplication consiste à définir wal_keep_segments suffisamment haut pour que les fichiers WAL qui pourraient être nécessaires ne soient pas tournés ou recyclés. L'inconvénient de cette approche est qu'il est difficile de déterminer quelle valeur convient le mieux à votre configuration. Vous n'aurez pas besoin d'entretien quotidien ou vous n'aurez pas besoin de conserver une grande quantité de fichiers WAL qui consomment votre stockage sur disque. Bien que cela fonctionne, ce n'est pas une solution idéale car le risque d'espace disque sur le maître peut entraîner l'échec des transactions entrantes.

Les approches alternatives pour ne pas utiliser les emplacements de réplication consistent à configurer PostgreSQL avec un archivage continu et à fournir une commande restore_commande pour donner à la réplique l'accès à l'archive. Pour éviter l'accumulation de WAL sur le primaire, vous pouvez utiliser un volume ou un périphérique de stockage séparé pour les fichiers WAL, par exemple, SAN ou NFS. Une autre chose concerne la réplication synchrone car elle nécessite que le nœud principal attende que les nœuds de secours valident la transaction. Cela signifie qu'il garantit que les fichiers WAL ont été appliqués aux nœuds de secours. Mais encore, il est préférable que vous fournissiez des commandes d'archivage à partir du primaire afin qu'une fois les WAL recyclés dans le primaire, soyez assuré que vous disposez de sauvegardes WAL en cas de récupération. Bien que dans certaines situations, la réplication synchrone ne soit pas une solution idéale car elle entraîne une surcharge de performances par rapport à la réplication asynchrone.

Types d'emplacements de réplication

Il existe deux types de slots de réplication. Ce sont :

Emplacements de réplication physique 

Peut être utilisé pour la réplication de flux standard. Ils veilleront à ce que les données ne soient pas recyclées trop tôt.

Emplacements de réplication logique

La réplication logique fait la même chose que les emplacements de réplication physique et est utilisée pour la réplication logique. Cependant, ils sont utilisés pour le décodage logique. L'idée derrière le décodage logique est de donner aux utilisateurs la possibilité de s'attacher au journal des transactions et de le décoder avec un plugin. Il permet d'extraire les modifications apportées à la base de données et donc au journal des transactions dans n'importe quel format et à n'importe quelle fin.

Dans ce blog, nous utiliserons des emplacements de réplication physiques et comment y parvenir à l'aide de ClusterControl.

Avantages et inconvénients de l'utilisation des slots de réplication

Les emplacements de réplication sont définitivement bénéfiques une fois activés. Par défaut, les "emplacements de réplication" ne sont pas activés et doivent être définis manuellement. Parmi les avantages de l'utilisation des slots de réplication, citons

  • Assure que le maître conserve suffisamment de segments WAL pour que tous les réplicas puissent les recevoir
  • Empêche le maître de supprimer des lignes qui pourraient provoquer un conflit de récupération sur les répliques
  • Un maître ne peut recycler le journal des transactions qu'une fois qu'il a été consommé par toutes les répliques. L'avantage ici est qu'un esclave ne peut jamais prendre tellement de retard qu'une resynchronisation est nécessaire.

Les emplacements de réplication comportent également quelques mises en garde.

  • Un emplacement de réplication orphelin peut entraîner une croissance illimitée du disque en raison des fichiers WAL empilés du maître
  • Les nœuds esclaves placés sous longue maintenance (comme des jours ou des semaines) et qui sont liés à un emplacement de réplication auront une croissance de disque illimitée en raison des fichiers WAL empilés du maître

Vous pouvez surveiller cela en interrogeant pg_replication_slots pour déterminer les slots qui ne sont pas utilisés. Nous reviendrons sur cela un peu plus tard.

Utilisation des emplacements de réplication 

Comme indiqué précédemment, il existe deux types de slots de réplication. Pour ce blog, nous utiliserons des emplacements de réplication physiques pour la réplication en continu.

Création d'un slot de réplication

Créer une réplication est simple. Vous devez invoquer la fonction existante pg_create_physical_replication_slot pour ce faire et doit être exécutée et créée dans le nœud maître. La fonction est simple,

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

par ex. Création d'un slot de réplication nommé slot1,

postgres=# SELECT pg_create_physical_replication_slot('slot1');

-[ RECORD 1 ]-----------------------+---------

pg_create_physical_replication_slot | (slot1,)

Les noms d'emplacement de réplication et sa configuration sous-jacente sont uniquement à l'échelle du système et non à l'échelle du cluster. Par exemple, si vous avez le nœud A (maître actuel) et les nœuds de secours nœud B et nœud C, en créant l'emplacement sur un nœud maître A, à savoir "emplacement 1", les données ne seront pas disponibles pour le nœud B et le nœud C. Par conséquent, lorsque le basculement/basculement est sur le point de se produire, vous devez recréer les emplacements que vous avez créés.

Supprimer un emplacement de réplication

Les emplacements de réplication inutilisés doivent être abandonnés ou supprimés. Comme indiqué précédemment, lorsqu'il existe des emplacements de réplication orphelins ou des emplacements qui n'ont été attribués à aucun nœud client ou de secours, cela peut entraîner des problèmes d'espace disque illimité s'ils ne sont pas supprimés. Il est donc très important que ceux-ci soient abandonnés lorsqu'ils ne sont plus utilisés. Pour le supprimer, invoquez simplement pg_drop_replication_slot. Cette fonction a la définition suivante :

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

Le supprimer est simple :

maximus_db=# select pg_drop_replication_slot('slot2');

-[ RECORD 1 ]------------+-

pg_drop_replication_slot |

Surveillance de vos slots de réplication PostgreSQL

La surveillance de vos slots de réplication est quelque chose que vous ne voulez pas manquer. Collectez simplement les informations de la vue pg_replication_slots dans le nœud principal/maître, comme ci-dessous :

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 |

Le résultat ci-dessus montre que le main_slot a été pris, mais pas main_slot2.

Une autre chose que vous pouvez faire est de surveiller le décalage par rapport aux créneaux dont vous disposez. Pour ce faire, vous pouvez simplement utiliser la requête basée sur l'exemple de résultat ci-dessous :

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

Mais redo_lsn n'est pas présent dans 9.6, doit utiliser redo_location, donc dans 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

Exigences relatives aux variables système

L'implémentation des emplacements de réplication nécessite un réglage manuel. Il y a des variables que vous devez garder à l'esprit qui nécessitent des modifications et qui doivent être spécifiées dans votre postgresql.conf. Voir ci-dessous :

  • max_replication_slots – Si défini sur 0, cela signifie que les emplacements de réplication sont totalement désactivés. Si vous utilisez PostgreSQL <10 versions, cet emplacement doit être spécifié autre que 0 (par défaut). Depuis PostgreSQL 10, la valeur par défaut est 10. Cette variable spécifie le nombre maximum de slots de réplication. Le définir sur une valeur inférieure au nombre d'emplacements de réplication actuellement existants empêchera le serveur de démarrer.
  • wal_level – doit être au moins un réplica ou supérieur (le réplica est la valeur par défaut). La définition de hot_standby ou archive sera mappée à la réplique. Pour un emplacement de réplication physique, une réplique suffit. Pour les emplacements de réplication logiques, la logique est préférée.
  • max_wal_senders – défini sur 10 par défaut, 0 dans la version 9.6, ce qui signifie que la réplication est désactivée. Nous vous suggérons de le définir au moins sur 16, en particulier lors de l'exécution avec ClusterControl.
  • hot_standby – dans les versions <10, vous devez définir ce paramètre sur qui est désactivé par défaut. Ceci est important pour les nœuds de secours, ce qui signifie que lorsqu'ils sont activés, vous pouvez vous connecter et exécuter des requêtes pendant la récupération ou en mode veille.
  • primary_slot_name :cette variable est définie via recovery.conf sur le nœud de secours. Il s'agit de l'emplacement à utiliser par le récepteur ou le nœud de secours lors de la connexion avec l'expéditeur (ou principal/maître).

Vous devez noter que ces variables nécessitent généralement un redémarrage du service de base de données afin de recharger de nouvelles valeurs.

Utilisation des slots de réplication dans un environnement ClusterControl PostgreSQL

Maintenant, voyons comment nous pouvons utiliser les emplacements de réplication physiques et les implémenter dans une configuration Postgres gérée par ClusterControl.

Déploiement des nœuds de base de données PostgreSQL

Commençons à déployer un cluster PostgreSQL à 3 nœuds à l'aide de ClusterControl en utilisant la version PostgreSQL 9.6 cette fois.

ClusterControl déploiera les nœuds avec les variables système suivantes définies en conséquence en fonction de leurs valeurs par défaut ou des valeurs ajustées. Dans :

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)

Dans les versions PostgreSQL> 9.6, la valeur par défaut de max_replication_slots est 10, ce qui est activé par défaut, mais pas dans les versions 9.6 ou inférieures, qui est désactivé par défaut. Vous devez attribuer max_replication_slots supérieur à 0. Dans cet exemple, j'ai défini max_replication_slots sur 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

et redémarré le service,

[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

Configuration des emplacements de réplication pour les nœuds principaux et de secours

Il n'y a pas d'option dans ClusterControl pour ce faire, vous devez donc créer vos emplacements manuellement. Dans cet exemple, j'ai créé les emplacements dans le primaire de l'hôte 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)

Vérifier ce que nous venons de créer montre,

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)

Maintenant, dans les nœuds de secours, nous devons mettre à jour le recovery.conf et ajouter la variable primary_slot_name et changer le nom de l'application afin qu'il soit plus facile d'identifier le nœud. Voici à quoi cela ressemble dans l'hôte 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'

Faire la même chose également dans l'hôte 192.168.30.120 mais en modifiant le nom de l'application et en définissant le primary_slot_name ='slot2'.

Vérification de la santé du slot de réplication :

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)

De quoi d'autre avez-vous besoin ?

Étant donné que ClusterControl ne prend pas en charge les emplacements de réplication pour le moment, vous devez prendre en compte certains éléments. Qu'est-ce que c'est? Rentrons dans les détails.

Processus de basculement/basculement

Lorsqu'un basculement automatique ou un basculement via ClusterControl a été tenté, les emplacements ne seront pas conservés sur les nœuds principal et de secours. Vous devez le recréer manuellement, vérifier si les variables sont correctement définies et modifier le fichier recovery.conf en conséquence.

Reconstruire un esclave à partir d'un maître

Lors de la reconstruction d'un esclave, le recovery.conf ne sera pas conservé. Cela signifie que vos paramètres recovery.conf ayant le primary_slot_name seront effacés. Vous devez le spécifier à nouveau manuellement et vérifier la vue pg_replication_slots pour déterminer si les slots sont correctement utilisés ou laissés orphelins.

Si vous souhaitez reconstruire le nœud esclave/de secours à partir d'un maître, vous devrez peut-être envisager de spécifier la variable d'environnement PGAPPNAME comme dans la commande ci-dessous :

$ 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

Spécifier le paramètre -R est très important afin de recréer le fichier recovery.conf, tandis que -S doit spécifier le nom d'emplacement à utiliser lors de la reconstruction du nœud de secours.

Conclusion

L'implémentation des emplacements de réplication dans PostgreSQL est simple, mais il y a certaines mises en garde dont vous devez vous souvenir. Lors du déploiement avec ClusterControl, vous devrez mettre à jour certains paramètres lors du basculement ou des reconstructions d'esclaves.