23.4. Serveurs de secours semi-automatique (Warm Standby) pour la
haute disponibilité
L'archivage continu peut être utilisé pour créer une configuration de
cluster de haute disponibilité (HA) avec
un ou plusieurs serveurs de secours,
prêt(s) à prendre en main les opérations en cas de défaillance du
serveur principal. Cette fonctionnalité est surtout connue sous le
nom de
Warm Standby
ou
Log
Shipping
.
Le serveur principal et le serveur de secours travaillent ensemble
pour fournir cette capacité, bien que les serveurs soient très
faiblement couplés. Le serveur principal opère en mode d'archivage
continu alors que chaque serveur de secours opère en mode de
récupération continue en lisant les fichiers WAL du serveur primaire.
Aucune modification des tables de la base n'est requise pour activer
cette capacité. Elle a de ce fait un coût modique en terme
d'administration supplémentaire en comparaison à d'autres approches
de réplication. Cette configuration a également un impact
relativement faible sur les performances du serveur principal.
Le déplacement direct des enregistrements des WAL (ou journaux) d'une
base à une autre est généralement appelé « transfert de journaux » (
log shipping
).
Sous PostgreSQL™, c'est un
transfert de fichiers, de sorte que les enregistrements WAL sont
transférés fichier par fichier. Les fichiers WAL peuvent être envoyés
facilement et sans surcoût quelque soit la distance, que ce soit sur
un système adjacent, sur un autre système du même site ou sur un
autre système de l'autre côté du globe. La bande passante requise par
cette technique varie en fonction du taux de transaction du serveur
principal. Le transfert de journaux par enregistrement (
record-based log
shipping
) est également réalisable, à l'aide de
procédures personnalisées, discutées dans
Section 23.4.4, « Transfert de journaux d'après les
enregistrements (
Record-based Log Shipping
) ».
L'envoi des journaux est asynchrone, ce qui signifie que les
enregistrements WAL sont envoyés après validation de la transaction.
De ce fait, il y a un léger risque de perte de données si le serveur
principal est l'objet d'une panne catastrophique : les transactions
qui ne sont pas encore transmises sont perdues. La taille de la
fenêtre des données perdues peut être réduite par l'utilisation du
paramètre archive_timeout. Celui-ci peut
être positionné à une valeur de quelques secondes seulement, si
nécessaire. Toutefois, une valeur aussi faible augmente
considérablement les besoins en bande passante du transfert de
fichiers. Si une valeur aussi basse est nécessaire, il peut être
préférable de s'intéresser au transfert de journaux par
enregistrement.
Le serveur de secours n'est pas accessible, car il est en permanence
occupé par la récupération. Les performances de récupération sont
suffisamment bonnes pour que l'attente soit réduite avant d'obtenir
une disponibilité complète une fois le serveur de secours activé. En
conséquence, on appelle cela une configuration de reprise
intermédiaire ou de secours semi-automatique (
warm standby
),
qui permet d'atteindre la haute disponibilité. La restauration d'un
serveur à partir d'une sauvegarde archivée de la base et de la
relecture des journaux prend considérablement plus de temps. Cette
technique n'offre qu'une solution de récupération suite à une panne,
mais pas de la haute disponibilité.
Il est généralement préférable de créer des serveurs primaire et de
secours aussi semblables que possible, au moins du point de vue du
serveur de bases de données. En particulier, les noms des chemins
associés aux
tablespaces
sont passés tels quels. Les
serveurs doivent donc, tous, posséder les mêmes chemins de montage
des
tablespaces
si cette fonctionnalité est
utilisée. Si CREATE TABLESPACE est exécuté sur le
serveur principal, tout nouveau point de montage nécessaire doit
être créé à la fois sur le serveur principal et sur tous les
serveurs de secours, avant l'exécution de la commande. Le matériel
ne doit pas obligatoirement être identique mais l'expérience prouve
qu'il est plus facile de maintenir deux systèmes identiques sur la
durée de vie de l'application et du système. Dans tous les cas,
l'architecture du matériel doit être identique -- le transfert d'un
système 32 bits à un 64 bits ne fonctionne pas.
En général, il n'est pas possible d'effectuer le transfert de
journaux entre serveurs de versions majeures différentes. La
politique des développeurs du « PostgreSQL
Global Development Group » consiste à ne pas modifier
les formats disque lors de mises à jour mineures. De ce fait, il
est possible d'utiliser des serveurs principal et de secours de
versions mineures différentes. Toutefois, aucune garantie formelle
n'est offerte à ce sujet. Il est préférable, dans la mesure du
possible, de conserver les serveurs primaire et de secours au même
niveau de version. Lors de la mise à jour vers une nouvelle version
mineure, la meilleure politique est de mettre à jour les serveurs
de secours en premier -- il y a plus de chances qu'une version
mineure sache lire les fichiers WAL d'une version mineure
précédente que le contraire.
Il n'y a pas de mode particulier requis pour activer un serveur de
secours. Les seules opérations sur les serveurs principal et de
secours sont des tâches normales d'archivage continu et de
récupération. Le seul point de contact entre les deux serveurs est
l'archive de fichiers WAL qu'ils partagent : le principal les
écrit, le serveur de secours les lit. Il est impératif que des
archives WAL de serveurs primaires différents ne soient pas
mélangées.
La magie qui permet à deux serveurs faiblement liés de travailler
ensemble réside dans une simple restore_command utilisée sur le serveur de secours
qui attend la disponibilité du prochain fichier WAL en provenance
du serveur principal. restore_command est
indiqué dans le fichier recovery.conf du
serveur de secours. En fonctionnement normal, le processus de
récupération attend un fichier dans l'archive WAL, remontant une
erreur si le fichier est indisponible. Dans le cas du serveur de
secours, il est normal que le fichier suivant n'existe pas. Il ne
reste donc qu'à attendre son arrivée. Une restore_command d'attente peut être obtenue par
l'écriture d'un script personnalisé qui boucle sur un test
d'apparition du prochain fichier WAL. Il faut également définir un
moyen de déclencher la bascule (
failover
), ce
qui interrompt la restore_command, sort de
la boucle et retourne une erreur au serveur de secours indiquant
que le fichier n'a pas été trouvé. Cela arrête alors la
récupération et le serveur de secours devient un serveur normal.
Un exemple de pseudocode de restore_command peut être :
triggered = false;
while (!NextWALFileReady() && !triggered)
{
sleep(100000L); /* wait for ~0.1 sec */
if (CheckForExternalTrigger())
triggered = true;
}
if (!triggered)
CopyWALFileForRecovery();
PostgreSQL™ ne fournit pas
de logiciel qui permette d'identifier une panne du serveur
principal et d'en notifier le serveur de secours. De nombreux
outils de ce type existent et sont bien intégrés à d'autres aspects
nécessaires à la réussite du
failover
, comme la migration d'adresse
IP.
Le déclenchement du
failover
est une partie importante de
la planification et de la conception. restore_command est exécutée complètement pour
chaque fichier WAL. Le processus exécutant restore_command est du coup créé et meurt pour
chaque fichier. Il n'y a, de ce fait, pas de démon ou de processus
serveur. Il n'est alors pas possible d'utiliser les signaux et un
gestionnaire de signal. Une notification plus permanente est
requise pour le déclenchement du
failover
. Il
est possible d'utiliser un simple dépassement de temps d'attente,
spécialement en conjonction avec un paramètre archive_timeout défini sur le serveur principal et
connu. Cela peut toutefois induire des erreurs, car un problème
réseau ou l'occupation du serveur principal peuvent suffire à
provoquer un
failover
. Un mécanisme de notification
tel que la création explicite d'un fichier déclencheur, quand cela
est possible, est moins source d'erreur.
Une procédure courte de configuration d'un serveur de secours est
indiquée dans la suite du document. Pour les détails complets de
chaque étape, on peut se référer aux sections précédentes.
La récupération traite l'archive WAL en lecture seule. Ainsi, dès
lors qu'un fichier WAL est copié sur le système de secours, il peut
être copié sur une cassette en même temps qu'il est lu pour la
récupération. De ce fait, un serveur de secours de haute
disponibilité peut tourner simultanément au stockage des fichiers à
plus long terme en vue d'une récupération après un désastre.
Pour les tests, il est possible d'exécuter le serveur principal et
celui de secours sur le même système. Cela n'apporte aucune
amélioration sur la robustesse du système, et ne peut pas être
présenté comme de la haute disponibilité.
23.4.3. Bascule (Failover)
Si le serveur principal rencontre un problème, le serveur de
secours doit commencer la procédure de
failover
.
Si le serveur de secours échoue, alors le
failover
n'est plus nécessaire. S'il peut être redémarré, même quelques
temps après, alors le processus de récupération peut être
immédiatement relancé en tirant parti de la restauration
réactivable (
Restartable Recovery
). Enfin, s'il ne
peut être redémarré, un nouveau serveur de secours doit être créé.
Si le serveur principal tombe et redémarre immédiatement, il faut
disposer d'un mécanisme l'informant qu'il n'est plus le serveur
principal. Ce mécanisme, connu sous l'acronyme STONITH (
Shoot The Other Node In The Head
),
permet d'éviter les situations où les deux systèmes pensent qu'ils
sont le serveur principal, ce qui peut engendrer une certaine
confusion et conduire à des pertes irrémédiables de données.
Un grand nombre de systèmes de
failover
utilisent simplement deux systèmes, le principal et celui de
secours, connectés par un mécanisme appelé « heartbeat » qui vérifie en permanence la
connectivité entre les deux systèmes et la viabilité du principal.
Il est aussi possible d'utiliser un troisième système, appelé
serveur témoin pour éviter tout problème de
failover
inapproprié. Cependant, la complexité supplémentaire peut s'avérer
inutile sauf s'il est configuré avec une attention suffisante et
des tests rigoureux.
Au moment où le
failover
est mis en place sur le
serveur de secours, un seul serveur est opérationnel. On parle
alors d'état dégénéré. L'ancien serveur de secours est devenu
serveur principal, l'ancien serveur principal est arrêté et peut le
rester. Il faut désormais recréer un serveur de secours, soit sur
l'ancien système principal, s'il peut redémarrer, soit sur un
troisième, de préférence nouveau, système. Lorsque cela est
réalisé, on peut considérer que les deux serveurs ont échangé leurs
rôles.
Certains administrateurs choisissent d'utiliser un troisième
serveur pour servir de sauvegarde au nouveau serveur principal le
temps que le serveur de secours devienne opérationnel. Toutefois,
cela complique assurément la configuration du système et les
processus opérationnels.
La bascule entre le serveur principal et celui de secours peut être
rapide, mais nécessite quelque temps pour repréparer le cluster de
failover
. Une bascule régulière est
encouragée car elle permet l'arrêt régulier de chaque système,
arrêt nécessaire pour maintenir la haute-disponiblité. Cela permet
également de tester les mécanismes de
failover
pour
s'assurer que cela fonctionnera toujours en cas de besoin. Il est
judicieux de rédiger ces procédures.
23.4.4. Transfert de journaux d'après les enregistrements
(Record-based Log Shipping)
PostgreSQL™ supporte
directement le transfert de journaux d'après fichiers (
file-based log
shipping
) tel que décrit plus haut. Il est également
possible d'implanter le transfert de journaux d'après
enregistrements, mais cela demande un développement adapté.
Un programme externe peut faire appel à la fonction pg_xlogfile_name_offset() (voir à ce propos la
Section 9.20,
« Fonctions d'administration système ») pour trouver
le nom du fichier et l'exact décalage en octet dans celui-ci de la
fin actuelle du WAL. Il peut alors accéder directement au fichier
WAL et copier les données depuis la dernière fin connue des WAL
jusqu'à l'actuelle vers le(s) serveur(s) de secours. Par cette
approche, la fenêtre de perte de données correspond au temps du
cycle d'interrogation du programme de copie. Elle peut alors être
très courte. Il n'y a, de plus, pas de surconsommation de la bande
passante du fait de l'archivage de fichiers segment partiellement
utilisés. Les scripts restore_command du
serveur de secours continuent de traiter avec l'ensemble des
fichiers WAL. De ce fait, les serveurs de secours ne peuvent pas,
en fonctionnement normal, disposer des données copiées par
incréments. Elles ne deviennent utilisables que lorsque le serveur
principal subit une panne -- le dernier fichier WAL partiel est
alors chargé dans le serveur de secours avant qu'il puisse
démarrer. Un codage correct de cette procédure nécessite une réelle
coopération entre le script de restore_command et le programme de copie des
donneés.
23.4.5. Sauvegardes incrémentales
Dans une configuration de reprise intermédiaire (
warm
standby
), il est possible de décharger le serveur
principal du coût des sauvegardes régulières des bases. Les
sauvegardes des bases peuvent, pour cela, être effectuées en
sauvegardant les fichiers d'un serveur de secours. Ce concept prend
le nom de sauvegardes incrémentales, accumulation des journaux de
modifications ou accumulation des modifications.
Si une sauvegarde des fichiers du serveur de secours est effectuée
alors qu'il retrace les journaux transférés du serveur principal,
il est possible de recharger ces données et de redémarrer le
processus de restauration sur le serveur de secours à partir du
dernier point de redémarrage. Il n'est alors plus nécessaire de
conserver les fichiers WAL précédant le point de redémarrage. En
cas de restauration, elle sera plus rapide à partir d'une
sauvegarde incrémentale qu'à partir de la sauvegarde originale.
Puisque le serveur de secours n'est pas « actif », il n'est pas possible d'utiliser
pg_start_backup() et pg_stop_backup() pour gérer le processus de
sauvegarde ; c'est à l'utilisateur de déterminer depuis quand il
doit conserver les fichiers de segment WAL pour avoir une
sauvegarde récupérable. Cela peut se faire en exécutant
pg_controldata sur le serveur de
secours. Ce programme inspecte le fichier de contrôle pour
déterminer l'emplacement du point de contrôle WAL actuel.