Vous êtes sur la page 1sur 8

0.

Introduction
1. Hot-Standby
1.1. Configuration du maître
1.2. Configuration du standby
1.3. (Re)Initialisation de la base du standby
1.4. Conclusion
2. Streaming replication
2.1. Configuration du maître
2.2. Configuration du standby
2.3. (Re)Initialisation de la base du standby
2.4. Conclusion
3. Aller plus loins

0. Introduction
La fonctionnalité de hot-standby de PostgreSQL 9.0 est similaire à la fonctionnalité de warm-
standby mais avec la possibilité de pouvoir exécuter des requêtes en lecture-seule sur l’hôte en
standby.

PostgreSQL 9.0 introduit aussi une fonction de streaming-replication qui permet de mettre à jour
plus rapidement l’hôte de standby.

En mode warm-standby, ou hot-standby, c’est la fonctionnalité de log-shipping qui permet de


mettre à jour l’hôte de standby en envoyant les segments de logs lorsque ceux-ci sont
complets.

Ce document va présenter la mise en oeuvre de ces fonctionnalités sur un cluster de deux


machines nommés `pg1’ pour le maître et `pg2’ pour le standby.

Pré-requis :
- Deux machines `pg1’ et `pg2’ avec PostgreSQL 9.0 (Ubuntu 10.04 LTS Server avec
PostgreSQL 9.0 du dépôt de paquets de Martin Pitt <https://launchpad.net/~pitti/
+archive/postgresql>).
- Accès SSH par clef privé/publique configuré sur les comptes `root’ et `postgres’ entre les deux
machines

1. Hot-Standby
1.1. Configuration du maître
Nous allons commencer par configurer le maître pour envoyer les logs sur le standby dans son
répertoire `/var/lib/postgresql/wal_xfer/’ :

root@pg1# vi /etc/postgresql/9.0/main/postgresql.conf
[...]
wal_level = hot_standby
archive_mode = 'on'
archive_command = 'rsync -a %p
postgres@pg2.local:/var/lib/postgresql/wal_xfer/%f'
[...]
root@pg1# service postgresql restart

`pg1’ est donc configuré pour générer des logs au format `hot_standby’.
Ensuite on active l’archivage des logs (archive_mode = ‘on’).
Pour finir, on déclare la commande qui permet d’envoyer le log sur `pg2’ (dans ce cas, on
utilisera rsync).

1.2. Configuration du standby


Pour fonctionner en mode hot-standby, il faut déclarer le mode `hot_standby = on’ dans la
configuration `postgresql.conf’ :

root@pg2# vi /etc/postgresql/9.0/main/postgresql.conf
[...]
hot_standby = on
[...]

Ensuite, il faut créer un fichier de configuration `recovery.conf’ qui permet de déclarer comment
sont « consommés » les fichiers de logs.

Pour cela, comme pour le warm-standby, on utilise la commande `pg_standby’ qui permet
d’intégrer en continue les logs qui seront présent dans le répertoire
`/var/lib/postgresql/wal_xfer/’ :

root@pg2# vi /var/lib/postgresql/9.0/main/recovery.conf
standby_mode = 'on'
restore_command = '/usr/lib/postgresql/9.0/bin/pg_standby -d -s 2
-l /var/lib/postgresql/wal_xfer %f %p %r'

1.3. (Re)Initialisation de la base du standby


Avant de démarrer le service postgresql sur le standby, il faut effectuer une copie binaire de la
base du maître.
Pour avoir une copie cohérente des bases binaires du maître, il va d’abord falloir lancer une
commande pg_start_backup() sur celui-ci, puis transférer les fichiers de la base sur le standby,
et enfin exécuter un pg_stop_backup().

Cette opération en nécessite pas l’arrêt de postgresql sur le maître.

Stopper postgresql sur pg2 :

root@pg2# service postgresql stop

Démarrer le backup sur pg1 :

root@pg1# echo "SELECT pg_start_backup('backup', true)" | su


postgres -c psql

Copier les bases binaires de pg1 vers pg2 :

root@pg1# rsync -avz --exclude


postmaster.pid /var/lib/postgresql/9.0/main/
root@pg2.local:/var/lib/postgresql/9.0/main/

Démarrer postgresql sur pg2 :

root@pg2# service postgresql start

Stopper le backup sur pg1 :

root@pg1# echo "SELECT pg_stop_backup()" | su postgresql -c psql

A présent, pg2 doit consommer les logs envoyés par pg1 et pouvoir être accessible en lecture :

root@pg2# su postgres -c psql


postgres=# \connect foo
foo=# SELECT count(*) FROM foo;
count
-------
304
(1 row)

foo=# INSERT INTO foo (id) VALUES (101010);


ERREUR: ne peut pas exécuter INSERT dans une transaction en
lecture seule

La base de standby est accessible en lecture, mais les opérations d’écriture sont mises en
échec.
1.4. Conclusion
Le mode de hot-standby se configure de la même manière que le warm-standby mais offre la
possibilité d’avoir un accès en lecture sur la base du standby.

Par contre, la mise à jour n’est pas en temps réel et n’est effectuée que lorsque le maître a
généré suffisamment de modifications pour remplir un segment WAL complet qui peut alors être
envoyé sur le standby.

Par défaut, la taille d’un segment est de 16Mo, ce qui fait que tant que 16Mo de log ne seront
pas complétés sur l’hôte maître, l’hôte standby ne recevra rien, et sera donc en retard par
rapport aux données présentes sur l’hôte maître. Typiquement, cela conduit à ce que le résultat
d’une écriture sur le maître n’apparaît pas instantanément sur l’hôte de standby.

Cette solution de hot-standby peut donc être une solution pour partager la charge de lecture sur
plusieurs machines, à condition que vos modifications ne soient pas fréquentes et que vous
acceptiez qu’il y ait un long délai pour que les modifications apparaissent sur tous les hôtes de
standby.

C’est pour combler ce problème que vient le streaming-replication qui permet d’avoir une
granularité plus fine dans la mise à jour du standby en transmettant les morceaux d’un segment
WAL sans attendre que celui-ci soit complet.

2. Streaming replication
Le streaming-replication permet une granularité plus fine dans la mise à jour du standby que ne
le permet le hot-standby.

La configuration est similaire au mode de hot-standby, sauf que le standby va initier une
connexion postgresql sur le maître pour être maintenu au courant des mise à jour de manière
plus rapide.

Par défaut on gardera le mécanisme de log-shipping afin de pouvoir re-initialiser un standby


sans contrainte de temps. Suite à la copie binaire du maître sur le standby, le temps que le
standby démarre, de l’activité sur le maître peut avoir généré beaucoup de modifications, et
comme par défaut les WAL ne sont pas archivés, la base du standby sera alors tout de suite
dé-synchronisée par rapport au maître. Si vous ne voulez pas conserver le log-shipping, il
faudra alors augmenter le paramètre `wal_keep_segments’ afin de conserver plus de WAL, et
que le standby puisse récupérer dans ces WAL les éléments qu’il lui manque.

2.1. Configuration du maître


La configuration du maître reprend la configuration du mode hot-standby, et ajoute le paramètre
`max_wal_senders’ afin de paramétrer le nombre max de clients de réplication.
Dans notre cas, on aura qu’un client de réplication :

root@pg1# vi /etc/postgresql/9.0/main/postgresql.conf
[...]
max_wal_senders = 1
wal_level = hot_standby
archive_mode = 'on'
archive_command = 'rsync -a %p
postgres@pg2.local:/var/lib/postgresql/wal_xfer/%f'
[...]

root@pg1# service postgresql restart

Le streaming-replication nécessite une connection du standby sur le maître.

Pour cela il faut donc ajuster les paramètres d’accès `pg_hba.conf’ pour autoriser cette
connection sur la base nommée `replication’ :

root@pg1# vi /etc/postgresql/9.0/main/pg_hba.conf
[...]
host replication postgres 10.0.0.2/32 trust

root@pg1# service postgresql restart

2.2. Configuration du standby


On configure le standby en `hot-standby’ :

root@pg2# vi /etc/postgresql/9.0/main/postgresql.conf
[...]
hot_standby = on
[...]

Ensuite, on paramètre le `recovery.conf’ comme suit :

root@pg2# vi /var/lib/postgresql/9.0/main/recovery.conf
standby_mode = 'on'
restore_command = 'cp -i /var/lib/postgresql/wal_xfer/%f %p'
archive_cleanup_command =
'/usr/lib/postgresql/9.0/bin/pg_archivecleanup
-d /var/lib/postgresql/wal_xfer/ %r'
primary_conninfo = 'host=pg1 port=5432 user=postgres'
On n’utilise plus `pg_standby’ pour la consommation des logs, puisque par la suite les
nouveaux logs seront gérés par la fonction de streaming-replication.

La connection de streaming-replication est déclarée dans `primary_conninfo’.

2.3. (Re)Initialisation de la base du standby


Comme dans le hot-standby, on doit initier le standby à partir d’une copie binaire du maître.

Stopper postgresql sur pg2 :

root@pg2# service postgresql stop

Démarrer le backup sur pg1 :

root@pg1# echo "SELECT pg_start_backup('backup', true)" | su


postgres -c psql

Copier les bases binaires de pg1 vers pg2 :

root@pg1# rsync -avz --exclude


postmaster.pid /var/lib/postgresql/9.0/main/
root@pg2.local:/var/lib/postgresql/9.0/main/

Stopper le backup sur pg1 :

root@pg1# echo "SELECT pg_stop_backup()" | su postgresql -c psql

Démarrer postgresql sur pg2 :

root@pg2# service postgresql start

A présent on peut regarder le contenu de la base sur le standby, et celui-ci sera mis à jour «
instantanément ».

On peut constater cela en faisant un simple INSERT d’un enregistrement dans une table du
maître, et voir que cet enregistrement est bien présent sur la table du standby, alors qu’en hot-
standby, cet enregistrement n’aurait été visible qu’après un temps variable, le temps que le
segment de WAL soit complet.

2.4. Conclusion
La mise en oeuvre du streaming-replication reprend donc le fonctionnement du hot-standby
pour le démarrage de la base du standby, et ensuite, une fois que le standby est connecté au
maître, il reçoit les mises à jour sur cette connection de réplication.
3. Extra
3.1. Pour aller plus loins
http://wiki.postgresql.org/wiki/Hot_Standby
http://wiki.postgresql.org/wiki/Binary_Replication_Tutorial
http://www.postgresql.org/docs/9.0/static/pgarchivecleanup.html

3.2. Script de re(init) de standby


Scripts de re(init) du standby utilisées pour le maquetage décrit ci-dessus.

--8<-- [ reinit-hotstandby.sh ]
#!/bin/sh

ssh root@pg2.local 'service postgresql stop'

echo "SELECT pg_start_backup('backup', true);" | su postgres -c psql


rsync -avz --delete --exclude
postmaster.pid /var/lib/postgresql/9.0/main/
root@pg2.local:/var/lib/postgresql/9.0/main/

ssh root@pg2.local "(echo \"standby_mode = 'on'\";


echo \"restore_command = '/usr/lib/postgresql/9.0/bin/pg_standby -d -s
2 -l /var/lib/postgresql/wal_xfer %f %p %r'\")
> /var/lib/postgresql/9.0/main/recovery.conf"

ssh root@pg2.local 'service postgresql start'

echo "SELECT pg_stop_backup();" | su postgres -c psql


-->8--

--8<-- [ reinit-streamingreplication.sh ]
#!/bin/sh

ssh root@pg2.local 'service postgresql stop'

echo "SELECT pg_start_backup('backup', true);" | su postgres -c psql


rsync -avz --delete --exclude
postmaster.pid /var/lib/postgresql/9.0/main/
root@pg2.local:/var/lib/postgresql/9.0/main/
echo "SELECT pg_stop_backup();" | su postgres -c psql
ssh root@pg2.local "(echo \"standby_mode = 'on'\";
echo \"restore_command = 'cp -i /var/lib/postgresql/wal_xfer/%f %p'\";
echo \"archive_cleanup_command =
'/usr/lib/postgresql/9.0/bin/pg_archivecleanup
-d /var/lib/postgresql/wal_xfer/ %r'\"; echo \"primary_conninfo =
'host=pg1.local port=5432 user=postgres'\")
> /var/lib/postgresql/9.0/main/recovery.conf"

ssh root@pg2.local 'service postgresql start'


-->8--

Vous aimerez peut-être aussi