Configuration de la réplication synchrone pour la haute disponibilité dans PostgreSQL

Apprenez à configurer la haute disponibilité PostgreSQL sans perte de données (RPO=0) en utilisant la réplication en flux synchrone. Ce tutoriel étape par étape couvre les configurations essentielles pour `wal_level`, les slots de réplication, `pg_basebackup`, et le réglage correct des paramètres `synchronous_commit` sur les serveurs primaire et de secours afin de garantir la durabilité des transactions dans les environnements critiques.

41 vues

Configuration de la réplication synchrone pour la haute disponibilité dans PostgreSQL

La configuration de PostgreSQL pour la haute disponibilité (HA) est cruciale pour toute application critique. Bien que la réplication asynchrone offre des avantages en termes de performance, elle comporte intrinsèquement un risque de perte de données si le serveur primaire tombe en panne avant que les modifications ne soient entièrement transmises au serveur de secours. La réplication synchrone en flux continu résout ce problème en garantissant qu'une transaction n'est considérée comme validée qu'une fois que les données ont été écrites avec succès dans le WAL (Write-Ahead Log) du serveur primaire et d'au moins un serveur de secours désigné. Cela assure un objectif de point de récupération (RPO) de zéro.

Ce guide complet vous présente les étapes de configuration essentielles nécessaires pour établir une configuration de réplication PostgreSQL robuste et sans perte de données. Nous nous concentrerons sur les paramètres critiques tels que wal_level et synchronous_commit qui sous-tendent cette architecture de haute disponibilité.

Prérequis

Avant de commencer, assurez-vous d'avoir deux serveurs PostgreSQL configurés (un primaire et un de secours) exécutant des versions majeures identiques de PostgreSQL. Les deux serveurs doivent avoir une connectivité réseau. Pour ce guide, nous supposons :

  • Nom d'hôte/IP primaire : pg_primary
  • Nom d'hôte/IP de secours : pg_standby
  • Utilisateur de réplication : repl_user (créé avec les permissions appropriées)
  • Nom de la base de données : mydb

Étape 1 : Configuration du serveur primaire

Le serveur primaire nécessite des paramètres spécifiques pour activer la réplication en flux continu et gérer le journal de transactions (Write-Ahead Log ou WAL) requis par les validations synchrones.

A. Ajustement de postgresql.conf sur le serveur primaire

Modifiez le fichier postgresql.conf du serveur primaire. Les paramètres suivants sont obligatoires pour la réplication en flux continu :

# --- Requis pour la réplication ---
listen_addresses = '*'         # Autorise les connexions depuis les serveurs de secours
wal_level = replica            # Doit être 'replica' ou supérieur (ex: 'logical')
max_wal_senders = 10           # Nombre max de connexions simultanées depuis les serveurs de secours
max_replication_slots = 10     # Slots nécessaires pour les flux de réplication persistants

# --- Essentiel pour la validation synchrone ---
synchronous_standby_names = '1 (standby_app_name)' # Spécifie les serveurs de secours requis

# --- Facultatif mais recommandé ---
wal_log_hints = on             # Recommandé pour une réplication plus sûre, bien qu'il augmente le volume du WAL
shared_preload_libraries = 'pg_stat_statements' # Si vous utilisez la surveillance

Explication des paramètres clés :

  • wal_level = replica : Cela garantit que suffisamment d'informations sont écrites dans le WAL pour permettre à un serveur de secours de reconstruire l'état de la base de données. Pour les validations synchrones, ce niveau est l'exigence minimale.
  • synchronous_standby_names : Il s'agit du paramètre central pour définir quels serveurs de secours doivent accuser réception des écritures. Nous le définissons en utilisant la syntaxe (N (nom_du_serveur_de_secours)). Si N=1, au moins un serveur de secours doit confirmer l'écriture avant que la transaction ne soit validée.

B. Configuration de l'authentification basée sur l'hôte (pg_hba.conf)

Le serveur primaire doit autoriser l'utilisateur de réplication des serveurs de secours à se connecter à des fins de réplication.

Ajoutez une entrée au fichier pg_hba.conf sur le serveur primaire :

# TYPE  BASE_DE_DONNÉES UTILISATEUR       ADRESSE                  MÉTHODE
host    replication     repl_user       pg_standby/32           scram-sha-256

Remplacez pg_standby/32 par l'adresse IP réelle ou le sous-réseau de votre serveur de secours.

C. Création du slot de réplication et de l'utilisateur

Connectez-vous à PostgreSQL sur le serveur primaire pour créer l'utilisateur et le slot de réplication nécessaires.

1. Créer l'utilisateur de réplication :

CREATE ROLE repl_user WITH REPLICATION LOGIN PASSWORD 'a_strong_password';

2. Créer le slot de réplication :

Ce slot garantit que les segments WAL sont conservés jusqu'à ce que le serveur de secours confirme leur réception, ce qui empêche la perte de données si le serveur de secours se déconnecte temporairement.

SELECT pg_create_physical_replication_slot('standby_app_name');
  • Remarque sur la dénomination : Le nom fourni ici (standby_app_name) doit correspondre au nom spécifié dans synchronous_standby_names sur le serveur primaire.

D. Redémarrage du serveur primaire

Appliquez toutes les modifications de configuration en redémarrant le service PostgreSQL sur le serveur primaire.

sudo systemctl restart postgresql

Étape 2 : Configuration du serveur de secours

Le serveur de secours est configuré pour diffuser les enregistrements WAL depuis le serveur primaire en utilisant une configuration de récupération.

A. Sauvegarde de base

Avant de commencer la diffusion, le serveur de secours a besoin d'une copie complète du répertoire de données du serveur primaire. Arrêtez d'abord PostgreSQL sur le serveur de secours.

sudo systemctl stop postgresql

Effectuez la sauvegarde de base à l'aide de pg_basebackup. Remplacez les chemins et les détails de connexion si nécessaire :

# Exemple utilisant l'utilitaire pg_basebackup
pg_basebackup -h pg_primary -D /var/lib/postgresql/15/main/ -U repl_user -P -Xs -R -W
  • -D : Le répertoire de données cible sur le serveur de secours.
  • -U : L'utilisateur de réplication.
  • -P : Afficher la progression.
  • -Xs : Inclure les fichiers WAL nécessaires pendant la sauvegarde de base.
  • -R : Crée automatiquement le fichier standby.signal et génère les paramètres de connexion nécessaires dans postgresql.auto.conf (ou la configuration de récupération).

B. Configuration de postgresql.conf sur le serveur de secours

Sur le serveur de secours, assurez-vous que postgresql.conf lui permet d'agir comme une réplique. Le paramètre clé ici est la définition du nom de l'application, qui doit correspondre au nom du slot utilisé sur le serveur primaire.

# --- Requis sur le serveur de secours ---
primary_conninfo = 'host=pg_primary port=5432 user=repl_user password=a_strong_password application_name=standby_app_name'
hot_standby = on          # Autorise les requêtes de lecture en mode récupération/secours

C. Démarrage du serveur de secours

Démarrez le service PostgreSQL sur le serveur de secours.

sudo systemctl start postgresql

Étape 3 : Vérification et test de la validation synchrone

Une fois que les deux serveurs sont en cours d'exécution, vérifiez la connexion puis testez le comportement synchrone.

A. Vérification de l'état de la réplication

Connectez-vous à la base de données primaire et vérifiez la vue pg_stat_replication :

SELECT client_addr, application_name, state, sync_state FROM pg_stat_replication;

Vous devriez voir une entrée pour standby_app_name avec sync_state défini sur sync.

B. Test de la validation synchrone

Le paramètre global qui dicte à quel point PostgreSQL attend est synchronous_commit. Pour un RPO=0, vous devez utiliser une valeur qui force la synchronisation.

1. Définition du comportement global

Si vous avez configuré synchronous_standby_names sur le serveur primaire comme indiqué à l'étape 1, le comportement par défaut forcera l'attente des serveurs de secours requis si synchronous_commit est défini sur on (par défaut) ou remote_write.

Pour la garantie la plus forte, définissez-le explicitement dans postgresql.conf sur remote_write ou remote_apply (si vous avez besoin que le serveur de secours ait vidé les données sur le disque, et pas seulement les ait reçues).

# Dans postgresql.conf sur le serveur primaire
synchronous_commit = remote_write

Attention : Définir synchronous_commit = remote_write ou on augmente considérablement la latence des transactions par rapport aux modes asynchrones (off ou local). Cette latence est directement corrélée à la vitesse du réseau entre le serveur primaire et le serveur de secours synchrone.

2. Test au sein d'une transaction

Pour tester de manière transactionnelle (sans nécessiter de modification de configuration globale), vous pouvez le définir par session ou par transaction :

-- Se connecter au serveur primaire

BEGIN;
SET LOCAL synchronous_commit = remote_write;

INSERT INTO sales (item, amount) VALUES ('Widget A', 100);
-- Cette insertion bloquera jusqu'à ce que 'standby_app_name' confirme la réception.

COMMIT;
-- La validation (COMMIT) ne réussit qu'après que le serveur de secours ait accusé réception de l'écriture WAL.

Si la connexion au serveur de secours synchrone est perdue pendant la transaction, le serveur primaire attendra indéfiniment (si le serveur de secours se déconnecte proprement) ou reviendra en arrière en fonction du paramètre synchronous_commit_fallback_on_error (qui est on par défaut, ce qui signifie que la transaction pourrait échouer ou se bloquer si le serveur primaire ne peut pas confirmer l'état de synchronisation).

Meilleures pratiques pour la HA synchrone

  • Utiliser des serveurs de secours dédiés : N'affectez à votre liste de réplication synchrone que les serveurs de secours qui sont physiquement proches (faible latence) du serveur primaire. Une latence élevée aura un impact sévère sur les performances d'écriture.
  • Surveiller le décalage de réplication : Même en mode synchrone, surveillez le décalage du serveur de secours. Un serveur de secours lent, qui est techniquement toujours 'synchrone' mais qui met trop de temps à traiter le WAL, peut toujours impacter l'expérience utilisateur.
  • Repli de connexion : Comprenez le paramètre synchronous_commit_fallback_on_error. S'il est défini sur off, un échec de communication avec le serveur de secours synchrone pendant une validation entraînera l'échec de la transaction sur le serveur primaire, empêchant une divergence potentielle des données, mais impactant immédiatement la disponibilité.
  • Utiliser plusieurs serveurs de secours : Pour une redondance maximale dans une configuration synchrone, configurez synchronous_standby_names = '2 (standby1, standby2)' pour exiger des validations de deux serveurs de secours distincts.