Le failover (ou bascule sur incident) sur disque partagé élimine la surcharge de synchronisation par l'existence d'une seule copie de la base de données. Il utilise un seul ensemble de disques partagé par plusieurs serveurs. Si le serveur principal échoue, le serveur en attente est capable de monter et démarrer la base comme s'il récupérait d'un arrêt brutal. Cela permet un failover rapide sans perte de données.
La fonctionnalité de matériel partagé est commune aux périphériques de stockage en réseau. Il est également possible d'utiliser un système de fichiers réseau bien qu'il faille porter une grande attention au système de fichiers pour s'assurer qu'il a un comportement POSIX complet (voir Section 19.2.2.1). Cette méthode comporte une limitation significative : si les disques ont un problème ou sont corrompus, le serveur primaire et le serveur en attente sont tous les deux non fonctionnels. Un autre problème est que le serveur en attente ne devra jamais accéder au stockage partagé tant que le serveur principal est en cours d'exécution.
Il est aussi possible d'utiliser cette fonctionnalité d'une autre façon avec une réplication du système de fichiers, où toutes les modifications d'un système de fichiers sont renvoyées sur un système de fichiers situé sur un autre ordinateur. La seule restriction est que ce miroir doit être construit de telle sorte que le serveur en attente dispose d'une version cohérente du système de fichiers -- spécifiquement, les écritures sur le serveur en attente doivent être réalisées dans le même ordre que celles sur le primaire. DRBD est une solution populaire de réplication de systèmes de fichiers pour Linux.
Les serveurs secondaires, warm et hot standby, (voir Section 27.2) peuvent conserver leur cohérence en lisant un flux d'enregistrements de WAL. Si le serveur principal échoue, le serveur secondaire contient pratiquement toutes les données du serveur principal et peut rapidement devenir le nouveau serveur primaire. Ça peut être synchrone mais ça ne peut se faire que pour le serveur de bases complet.
Un serveur secondaire peut être implémenté en utilisant la recopie de journaux par fichier(Section 27.2) ou la streaming replication (réplication en continu ou en flux, voir Section 27.2.5), ou une combinaison des deux. Pour des informations sur le hot standby, voyez Section 27.4..
La réplication logique autorise un serveur de bases de données à envoyer un flux de modifications de données à un autre serveur. La réplication logique de PostgreSQL construit un flux de modifications logiques de données à partir des journaux de transactions. La réplication logique permet la réplication des modifications de données de tables individuelles. La réplication logique ne requiert pas qu'un serveur particulier soit désigné comme serveur primaire ou secondaire, mais autorise le flux de données dans plusieurs directions. Pour plus d'informations sur la réplication logique, voir Chapitre 31. Au travers de l'interface de décodage logique (Chapitre 49), les extensions tierces peuvent aussi fournir des fonctionnalités similaires.
Une architecture de réplication basée sur des triggers canalise habituellement les requêtes de modification de données vers un serveur primaire précis. Opérant table par table, le serveur primaire envoie alors les données modifiées (généralement) de façon asynchrone vers les serveurs secondaires. Les serveurs secondaires peuvent répondre aux requêtes qu'ils reçoivent alors que le serveur primaire est fonctionnel. Ils peuvent parfois permettre quelques modifications de données localement ou même une activité en écriture. Cette forme de réplication est souvent utilisée pour gérer de grosses requêtes analytiques ou de type Data Warehouse.
Slony-I est un exemple de ce type de réplication, avec une granularité par table et un support des secondaires multiples. Comme il met à jour le serveur secondaire de façon asynchrone (par lots), il existe une possibilité de perte de données pendant un failover.
Avec les middleware de réplication basés sur le SQL, un programme intercepte chaque requête SQL et l'envoie à un ou tous les serveurs. Chaque serveur opère indépendamment. Les requêtes en lecture/écriture doivent être envoyées à tous les serveurs pour que chaque serveur reçoive les modifications. Les requêtes en lecture seule ne peuvent être envoyées qu'à un seul serveur, ce qui permet de distribuer la charge de lecture.
Si les requêtes sont envoyées sans modification, les fonctions comme
random()
, CURRENT_TIMESTAMP
ainsi
que les séquences ont des valeurs différentes sur les différents serveurs.
Cela survient parce que chaque serveur opère indépendamment alors que
les requêtes SQL sont diffusées (et non les données
modifiées). Si cette solution est inacceptable, le
middleware ou l'application doivent
déterminer ces valeurs à partir d'une seule source, et les utiliser dans
les requêtes d'écriture. Il est impératif que
toute transaction soit validée ou annulée sur tous les serveurs,
éventuellement par validation en deux phases (PREPARE TRANSACTION et COMMIT PREPARED).
Pgpool-II et Continuent
Tungsten sont des exemples de ce type de réplication.
Pour les serveurs qui ne sont pas connectés en permanence ou qui ont des liens de communication lents, comme les ordinateurs portables ou les serveurs distants, conserver la cohérence des données entre les serveurs est un challenge. L'utilisation de la réplication asynchrone multi-primaires permet à chaque serveur de fonctionner indépendamment. Il communique alors périodiquement avec les autres serveurs pour identifier les transactions conflictuelles. La gestion des conflits est alors confiée aux utilisateurs ou à un système de règles de résolution. Bucardo est un exemple de ce type de réplication.
Dans les réplications synchrones multi-primaires, tous les serveurs acceptent les requêtes en écriture. Les données modifiées sont transmises du serveur d'origine à tous les autres serveurs avant toute validation de transaction.
Une activité importante en écriture peut être la cause d'un verrouillage excessif et de délai dans la validation des transactions, ce qui peut conduire à un effondrement des performances. Dans les faits, les performances en écriture sont souvent pis que celles d'un simple serveur.
Tous les serveurs acceptent les requêtes en lecture.
Certaines implantations utilisent les disques partagés pour réduire la surcharge de communication.
Les performances de la réplication synchrone multi-primaires sont meilleures lorsque
les opérations de lecture représentent l'essentiel de la charge, alors que
son gros avantage est l'acceptation des requêtes d'écriture par tous les
serveurs --
il n'est pas nécessaire de répartir la charge entre les serveurs
primaires et secondaires et, parce que les modifications de données sont envoyées
d'un serveur à l'autre, les fonctions non déterministes, comme
random()
, ne posent aucun problème.
PostgreSQL n'offre pas ce type de réplication, mais la validation en deux phases de PostgreSQL (PREPARE TRANSACTION et COMMIT PREPARED) autorise son intégration dans une application ou un middleware.
La Tableau 27.1 résume les possibilités des différentes solutions listées plus-haut.
Tableau 27.1. Matrice de fonctionnalités : haute disponibilité, répartition de charge et réplication
Fonctionnalité | Disques partagés | Répl. par système de fichiers | Envoi des journaux de transactions | Répl. logique | Répl. par triggers | Middleware de Répl. SQL | Répl. asynch. MM | Répl. synch. MM |
---|---|---|---|---|---|---|---|---|
Exemple populaires | NAS | DRBD | répl. en flux interne | répl. logique interne, pglogical | Londiste, Slony | pgpool-II | Bucardo | |
Méthode de comm. | Disque partagé | Blocs disque | WAL | décodage logique | Lignes de tables | SQL | Lignes de tables | Lignes de tables et verrous de ligne |
Ne requiert aucun matériel spécial | • | • | • | • | • | • | • | |
Autorise plusieurs serveurs primaires | • | • | • | • | ||||
Pas de surcharge sur le serveur primaire | • | • | • | • | ||||
Pas d'attente entre serveurs | • | with sync off | with sync off | • | • | |||
Pas de perte de données en cas de panne du primaire | • | • | with sync on | with sync on | • | • | ||
Les secondaires acceptent les requêtes en lecture seule | avec un hot standby | • | • | • | • | • | ||
Granularité de niveau table | • | • | • | • | ||||
Ne nécessite pas de résolution de conflit | • | • | • | • | • | • |
Certaines solutions n'entrent pas dans les catégories ci-dessus :
Le partitionnement des données divise les tables en ensembles de données. Chaque ensemble ne peut être modifié que par un seul serveur. Les données peuvent ainsi être partitionnées par bureau, Londres et Paris, par exemple, avec un serveur dans chaque bureau. Si certaines requêtes doivent combiner des données de Londres et Paris, il est possible d'utiliser une application qui requête les deux serveurs ou d'implanter une réplication primaire/secondaire pour conserver sur chaque serveur une copie en lecture seule des données de l'autre bureau.
La plupart des solutions ci-dessus permettent à plusieurs serveurs de répondre à des requêtes multiples, mais aucune ne permet à une seule requête d'être exécutée sur plusieurs serveurs pour se terminer plus rapidement. Cette solution autorisent plusieurs serveurs à travailler ensemble sur une seule requête. Ceci s'accomplit habituellement en répartissant les données entre les serveurs, chaque serveur exécutant une partie de la requête pour renvoyer les résultats à un serveur central qui les combine et les renvoie à l'utilisateur. Cela peut également se faire en utilisant PL/Proxy.
Il faut aussi noter que puisque PostgreSQL est un outil libre et facilement extensible, un certain nombre de sociétés se sont basées sur PostgreSQL pour créer leurs solutions propriétaires avec des possibilités spécifiques de failover, réplication ou répartition de charge. Cela ne sera toutefois pas abordé ici.