web-dev-qa-db-fra.com

Comment puis-je réparer un esclave PostgreSQL 9.3 qui ne peut pas suivre le maître?

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:

  1. Définir max_wal_senders=5
  2. Définissez 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:

  1. Enregistrer les fichiers de configuration dans le répertoire de données (c.-à-d. pg_hba.conf pg_ident.conf postgresql.conf recovery.conf)
  2. Effacez le répertoire de données (rm -rf /var/lib/pgsql/9.3/data/*). Cela semble être requis par pg_basebackup.
  3. Exécutez la commande suivante: 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.

14
Oleg Dulin

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

22
Ben Grimm

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. 

0
linehrr

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. 

0
Oleg Dulin