Styles

vendredi 6 mars 2015

Histoire de la réplication dans PostgreSQL

Cet article est une traduction par mes soins de l'article de Peter Eisentraut : The history of replication in PostgreSQL, publiée avec son autorisation.

2001: PostgreSQL 7.1: le journal à écriture anticipée

PostgreSQL 7.1 a lancé le Journal à Ecriture Anticipée (Write-ahead log : WAL). Avant cette version, tous les fichiers de données ouverts devaient être fsyncés sur chaque commit, ce qui était très lent. La lenteur du fsync est encore un problème aujourd'hui, mais maintenant nous sommes seulement préoccupés par le fsyncage du WAL et le fsyncage des fichiers de données au cours du processus de point de contrôle (checkpoint). À l'époque, nous avions à fsyncer tout, tout le temps.

Dans la conception originale de POSTGRES universitaire, l'absence d'un journal était intentionnel, et se démarquait des architectures largement basées sur la journalisation comme Oracle. Dans Oracle, vous avez besoin de faire un retour arrière sur les modifications dans le journal. Dans PostgreSQL, le système de stockage sans écrasement prend soin de cela. Mais, probablement, personne n'a pensé aux implications de fsync à l'époque.

Notez que le WAL était vraiment juste un détail d'implémentation à ce stade. Vous ne pouviez pas le lire ou l'archiver.

2004: Slony

Juste pour le contexte: Slony-I 1.0 est sorti en Juillet 2004.

2005: PostgreSQL 8.0: récupération à un point donné

PostgreSQL 8.0 a ajouté la possibilité de copier le WAL ailleurs, et plus tard le lire à nouveau, soit en entier soit jusqu'à un point donné dans le temps, d'où le nom de récupération à un point donné (Point-In-Time Recovery : PITR) pour cette fonctionnalité. Cette fonctionnalité était principalement destinée à laisser tomber pg_dump comme méthode de sauvegarde. Jusque-là, la seule méthode de sauvegarde existante était un vidage complet (dump), qui devenait malaisé plus les bases de données augmentaient. D'où cette méthode consistant à prendre occasionnellement une sauvegarde de base, qui est la partie coûteuse, puis à ajouter les parties du WAL, ce qui est moins coûteux.

Les mécanismes de configuration de base que nous utilisons encore aujourd'hui, par exemple, le fichier recovery.conf, ont été introduits dans le cadre de cette fonctionnalité.

Mais toujours pas de réplication ici.

2008: PostgreSQL 8.3: pg_standby

Des malins ont fini par comprendre que si vous archiviez le WAL sur un serveur et en même temps vous le récupériez (recover) à l'infini sur un autre, vous aviez une configuration de réplication. Vous pouviez probablement le faire avec vos propres scripts dès là 8.0, mais PostgreSQL 8.3 a ajouté le programme pg_standby dans contrib, ce qui donna à chacun un outil standard. Ainsi, on peut dire sans doute que la 8.3 fut la première version qui contint un semblant de solution de réplication intégré.

Le serveur de secours effectuait une récupération permanente jusqu'à sa promotion, de sorte qu'il ne pouvait être lu pendant qu'il répliquait. C'est ce que maintenant nous appelons un secours semi-automatique (warm standby).

Je pense que beaucoup d'installations PostgreSQL 8.3 refusent de mourir parce que c'est la première version où vous pouviez facilement avoir un serveur de réserve assez à jour, sans avoir recours à des outils complexes et parfois problématiques comme Slony ou DRBD.

2010: PostgreSQL 9.0: secours automatique, réplication par flux

Dans PostgreSQL 9.0, deux fonctions de réplication importantes sont arrivés indépendamment l'une de l'autre. Tout d'abord, la possibilité de se connecter à un serveur de secours en mode lecture seule, ce qui s'appelle un secours automatique (hot standby). Alors qu'auparavant, un serveur de secours était principalement utile uniquement comme réserve au cas où le serveur primaire tombait, avec le secours automatique, vous pouvez utiliser les serveurs secondaires pour y répartir la charge de lecture seule.

Deuxièmement, au lieu de s'en remettre uniquement aux archives WAL et aux fonctionnalités de récupération pour transporter les données du WAL, un serveur de secours peut se connecter directement au serveur principal via le protocole libpq existant et obtenir les données du WAL de cette manière, ce qu'on appelle la réplication par flux (streaming replication). Son utilisation principale dans cette version permettait au secours d'être plus à jour, peut-être de l'ordre de quelques secondes, plutôt que de quelques minutes avec l'approche basée sur l'archivage. Pour une configuration robuste, vous aviez encore besoin de mettre en place un archivage. Mais la réplication par flux était également une fonctionnalité tournée vers l'avenir qui finirais par faciliter la mise en place de véritables configurations de réplication, en réduisant la dépendance envers l'ancien mécanisme d'archivage.

PostgreSQL 9.0 fut la première version où l'on put prétendre que PostgreSQL "supporte la réplication" sans avoir à évoquer de restrictions ou s'excuser. Même s'il est prévu qu'elle atteigne sa fin de vie (End of Life : EOF) cette année, je me attends à ce que cette version continue à vivre pendant un bon moment.

2011: PostgreSQL 9.1: pg_basebackup, la réplication synchrone

pg_basebackup a été l'une des fonctionnalités permise par la réplication par flux qui rendit les choses plus facile. Au lieu d'avoir à utiliser des outils externes comme rsync pour les sauvegardes de base, pg_basebackup utilise une connexion libpq normale pour sortir une sauvegarde de base, évitant ainsi des configurations compliquées de connexion et d'authentification pour les outils externes. (Certaines personnes continuent de préférer rsync car il est plus rapide pour eux.)

PostgreSQL 9.1 a également ajouté la réplication synchrone, qui s'assure que les données sont répliquées sur le serveur de secours désigné avant que le COMMIT indique un succès. Cette fonctionnalité est souvent mal comprise par les utilisateurs. Bien qu'elle vous assure que vos données soient sur au moins deux serveurs à tout moment, elle pourrait en fait réduire la disponibilité de votre système, parce que si le serveur de secours tombe, le serveur primaire tombera aussi, sauf si vous avez un troisième serveur disponible pour prendre en charge la tâche synchrone de secours.

C'est peut-être moins largement connu mais PostgreSQL 9.1 a également ajouté la fonction pg_last_xact_replay_timestamp pour surveiller facilement le décalage du secours.

D'après mon expérience, la mise à disposition de pg_basebackup et pg_last_xact_replay_timestamp a fait de PostgreSQL 9.1 la première version où gérer la réplication était relativement facile. Remonter plus loin, et vous pourriez vous sentir contraint par les outils disponibles. Mais en 9.1, ce ne est pas très différent de ce qui est disponible dans les versions les plus récentes.

Cette photo est © Malcolm Cerfonteyn - CC BY 2.0

2012: PostgreSQL 9.2: réplication en cascade

Pas aussi largement acclamé, plus pour les amateurs de Slony peut-être, PostgreSQL 9.2 permis aux serveurs de secours d'aller chercher leurs données de réplication par flux à partir d'autres serveurs de secours. Une conséquence notamment de cela est que pg_basebackup pouvait récupérer les données à partir d'un serveur de secours, laissant ainsi la charge hors du serveur principal, pour la mise en place d'un nouveau serveur de secours ou une copie autonome.

2013: PostgreSQL 9.3: le serveur de secours peut suivre le changement de chronologie

Cela n'a même pas été relevé dans les faits marquants de la version. Dans PostgreSQL 9.3, lorsqu'un primaire a deux secours, et l'un des secours est promu, l'autre secours peut continuer à suivre le nouveau primaire. Dans les versions précédentes, le deuxième secours devait être reconstruit. Cette amélioration rend les changements dynamiques d'infrastructure beaucoup plus simples. Non seulement elle élimine le temps, les soucis, et l'impact sur les performances de la mise en place d'un nouveau secours, plus important encore, elle évite la situation, après une promotion, de n'avoir aucun serveur de secours à jour pendant un certain temps.

2014: PostgreSQL 9.4: emplacements de réplication, décodage logique

Le décodage logique est ce qui a retenu le plus l'attention pour la nouvelle version PostgreSQL 9.4, mais je pense que les emplacements de réplication (replication slots) représentent la fonctionnalité majeure, peut-être la plus grande fonctionnalité de réplication depuis PostgreSQL 9.0. Notez que pendant que la réplication par flux est devenu de plus en plus sophistiquée au fil des ans, vous avez toujours besoin d'archiver le WAL pour la robustesse complète. C'est parce que le serveur primaire ne garde pas de liste de ses serveurs de secours supposés, il ne fait que transférer le flux WAL à qui que ce soit le demande, s'il se trouve l'avoir à disposition. Si le serveur de secours était suffisamment en retard, la réplication par flux échouait, et la récupération par le recours à l'archive devenait nécessaire. Si vous n'aviez pas d'archive, le serveur de secours n'était alors plus en mesure de rattraper son retard et devait être reconstruit. Et ce mécanisme d'archivage n'a essentiellement jamais changé depuis la version 8.0, quand il avait été conçu pour un but totalement différent. Ainsi, une configuration de réplication est en fait assez compliqué: Vous devez configurer un chemin d'accès du primaire au secours (pour l'archivage) et un chemin d'accès du secours au primaire (pour le flux). Et si vous vouliez mettre plusieurs secours, en cascade, le maintien de l'archive pouvais devenir vraiment compliqué. En outre, je pense que beaucoup de configurations d'archivage ont un paramétrage problématique de archive_command. Par exemple, est-ce que votre archive_command réalise un fsync du fichier du côté le recevant ? Probablement pas.

Plus maintenant : Dans PostgreSQL 9.4, vous pouvez configurer ces fameux emplacements de réplication, ce qui signifie concrètement que vous enregistrez sur le primaire la présence d'un secours, et le primaire garde le WAL pour chaque secours jusqu'à ce qu'ils l'aient tous récupéré. Avec cela, vous pouvez vous débarrasser complètement de l'archivage, à moins que vous en ayez besoin pour faire une véritable sauvegarde.

2015? PostgreSQL 9.5? pg_rewind?

Un des problèmes restants est que la promotion d'un secours rend l'ancien primaire incapable de changer de cap et de suivre le nouveau primaire. Si vous basculez parce que l'ancien primaire est mort, alors ce n'est pas un problème. Mais si vous voulez juste échanger le primaire et le secours, peut-être parce que le secours dispose d'un matériel plus puissant, l'ancien primaire, désormais un secours, doit être reconstruit entièrement à partir de zéro. Transformer un ancien primaire en un nouveau secours sans une nouvelle sauvegarde complète de base est un problème assez complexe, mais un outil qui peut le faire (actuellement nommé pg_rewind ) est proposé pour inclusion dans la prochaine version de PostgreSQL.

Au-delà

Un des problèmes que cette évolution de la réplication a créés est que la configuration est plutôt idiosyncratique, assez compliquée à mettre en place correctement, et presque impossible à généraliser suffisamment pour la documentation, les tutoriels,... Supprimer l'archivage avec 9.4 pourrait résoudre certains de ces points, mais configurer rien que la réplication par flux est toujours étrange, et encore plus étrange si vous ne savez pas comment tout cela est arrivé jusqu'ici. Vous devez modifier plusieurs paramètres obscurs de configuration, certains sur le primaire, certains sur le secours, dont certains nécessitent un redémarrage complet du serveur primaire. Et ensuite vous avez besoin de créer un nouveau fichier de configuration recovery.conf, même si vous ne voulez pas de récupérer quoi que ce soit. Apporter des changements dans ce domaine est essentiellement un processus politique complexe, parce que le système actuel a bien servi les gens pendant de nombreuses années, et arriver avec un nouveau système qui est objectivement meilleur et adresse tous les cas d'utilisation existants est lourd.

Un autre problème est que toutes ces fonctionnalités se basent fortement sur le mécanisme de WAL, et cela contraint tous les usages du WAL de diverses manières. Par exemple, il y a des optimisations qui ne passent pas par la journalisation WAL dans certaines circonstances, mais si vous voulez de la réplication, vous ne pouvez pas les utiliser. Qui ne veut pas faire de la réplication ? En plus, le WAL couvre un système de base de données complet et marche en tout ou rien. Vous ne pouvez pas répliquer seulement certaines tables, par exemple, ou consolider les journaux provenant de deux sources différentes.

Que diriez-vous de ne pas tout baser sur le WAL? Avoir deux journaux différents pour deux objectifs différents. Cela a été discuté, en particulier au moment où la réplication par flux a été construite. Mais alors vous avez besoin de deux journaux qui sont quasiment identiques. Et le WAL est par conception un goulot d'étranglement, alors créer un autre journal créerait probablement des problèmes de performance.

Le décodage logique brise nombre de ces restrictions et sera probablement la fondation pour le prochain tour des fonctionnalités majeures de réplication. Par exemple, la réplication partielle et la réplication multi-maître, certaines étant déjà en cours d'élaboration.

Que pouvons-nous attendre de la journalisation WAL pure et simple en attendant ? Une configuration plus facile est demandée fréquemment. Mais peut-on s'attendre à des sauts importants en terme de fonctionnalité? Qui sait. Il fut un temps, quelque chose comme la secours automatique était vu comme presque impossible. Donc il pourrait encore y avoir des surprises.

Aucun commentaire: