Nous avons une configuration de réplication maître-esclave comme suit.
Sur le maître:
postgresql.conf
a la réplication configurée comme suit (ligne commentée supprimée pour plus de brièveté):
max_wal_senders = 1
wal_keep_segments = 8
Sur l'esclave:
Même postgresql.conf
que sur le maître. recovery.conf
ressemble à ceci:
standby_mode = 'on'
primary_conninfo = 'Host=master1 port=5432 user=replication password=replication'
trigger_file = '/tmp/postgresql.trigger.5432'
Lors de la configuration initiale, nous avons effectué des tests simples et confirmé que la réplication fonctionnait correctement. Cependant, lorsque nous avons effectué le chargement initial des données, seules certaines de ces données ont été transmises à l'esclave.
Le journal de Slave est maintenant rempli de messages qui ressemblent à ceci:
< 2015-01-23 23:59:47.241 EST >LOG: started streaming WAL from primary at F/52000000 on timeline 1
< 2015-01-23 23:59:47.241 EST >FATAL: could not receive data from WAL stream: ERROR: requested WAL segment 000000010000000F00000052 has already been removed
< 2015-01-23 23:59:52.259 EST >LOG: started streaming WAL from primary at F/52000000 on timeline 1
< 2015-01-23 23:59:52.260 EST >FATAL: could not receive data from WAL stream: ERROR: requested WAL segment 000000010000000F00000052 has already been removed
< 2015-01-23 23:59:57.270 EST >LOG: started streaming WAL from primary at F/52000000 on timeline 1
< 2015-01-23 23:59:57.270 EST >FATAL: could not receive data from WAL stream: ERROR: requested WAL segment 000000010000000F00000052 has already been removed
Après quelques analyses et une aide sur le canal #postgresql IRC, je suis parvenu à la conclusion que l'esclave ne pouvait pas suivre le maître. Ma solution proposée est la suivante.
Sur le maître:
max_wal_senders=5
wal_keep_segments=4000
. Oui, je sais que c'est très élevé, mais j'aimerais surveiller la situation et voir ce qui se passe. J'ai de la place sur le maître.Sur l'esclave:
pg_hba.conf pg_ident.conf postgresql.conf recovery.conf
)rm -rf /var/lib/pgsql/9.3/data/*
). Cela semble être requis par pg_basebackup
.pg_basebackup -h master -D /var/lib/pgsql/9.3/data --username=replication --password
Est-ce que je manque quelque chose? Existe-t-il un meilleur moyen de mettre à jour l'esclave sans avoir à recharger toutes les données?
Toute aide est grandement appréciée.
Les deux options importantes pour traiter la WAL pour réplication en continu :
wal_keep_segments
doit être réglé suffisamment haut pour permettre à un esclave de rattraper son retard après un délai raisonnable (par exemple, un volume de mises à jour élevé, un esclave hors ligne, etc.).
archive_mode
active l'archivage WAL qui peut être utilisé pour récupérer des fichiers plus anciens que ceux fournis par wal_keep_segments
. Les serveurs esclaves ont simplement besoin d’une méthode pour extraire les segments WAL. NFS est la méthode la plus simple, mais tout, de scp à http, en passant par les bandes, fonctionnera aussi longtemps qu'il sera possible de créer un script.
# on master
archive_mode = on
archive_command = 'cp %p /path_to/archive/%f'
# on slave
restore_command = 'cp /path_to/archive/%f "%p"'
Lorsque l'esclave ne peut pas extraire le segment WAL directement du maître, il tentera d'utiliser le restore_command
pour le charger. Vous pouvez configurer l'esclave pour supprimer automatiquement les segments à l'aide du paramètre archive_cleanup_command
.
Si l'esclave se trouve dans une situation où le prochain segment WAL dont il a besoin est absent du maître et de l'archive, il n'y aura aucun moyen de récupérer systématiquement la base de données. L'option raisonnable seulement consiste alors à nettoyer le serveur et à recommencer à partir d'un nouveau pg_basebackup
.
en fait, pour récupérer, vous n’avez pas besoin de supprimer toute la base de données et de repartir de zéro. Puisque le maître a un binaire à jour, vous pouvez faire ce qui suit pour récupérer l’esclave et le ramener à in-sync:
psql -c "select pg_start_backup('initial_backup');"
rsync -cva --inplace --exclude=*pg_xlog* <data_dir> slave_IP_address:<data_dir>
psql -c "select pg_stop_backup();"
Remarque:
1. l'esclave doit être refusé par service stop
2. le maître passera en lecture seule à cause de la requête pg_start_backup
3. le maître peut continuer à servir les requêtes en lecture seule
4. ramener l'esclave à la fin des marches
Je l'ai fait dans prod, cela fonctionne parfaitement pour moi. esclave et maître sont synchronisés et il n’ya aucune perte de données.
Comme Ben Grimm l'a suggéré dans les commentaires, il s'agit de s'assurer que les segments ont la valeur maximale possible pour permettre à l'esclave de se rattraper.