Aller au contenu principal

Réplication de Base de Données

← Retour au Guide des Opérations


Table des Matières


Aperçu

OmniHSS utilise PostgreSQL avec réplication logique bidirectionnelle pour des déploiements multi-sites à haute disponibilité. Chaque site fonctionne comme un primaire en lecture/écriture indépendant — il n'y a pas de maître unique ou de répliques en lecture seule.

Caractéristiques Clés

  • Les Deux Sites en Lecture/Écriture : Chaque site a une base de données primaire complète. Les écritures locales sont instantanées, quelle que soit la qualité du lien inter-site
  • Réplication Asynchrone : Les modifications se répliquent via le Write-Ahead Log (WAL) de PostgreSQL. Aucune écriture n'est bloquée en attendant qu'un site distant accuse réception
  • Tolérant aux Partitions : Si le lien inter-site tombe, les deux sites continuent de fonctionner indépendamment. Les segments WAL s'accumulent localement et se rejouent automatiquement lorsque le lien se rétablit
  • Pas de Quorum Requis : Contrairement aux approches de cluster synchrones, il n'y a pas de concept de quorum. Un déploiement sur un seul site fonctionne de la même manière qu'un déploiement multi-sites
  • Clés Primaires UUID : Tous les enregistrements utilisent des clés primaires UUIDv4, éliminant les collisions d'ID entre les sites sans coordination

Comment Cela Diffère de la Réplication Synchrone

SynchroneRéplication Logique Asynchrone
Latence d'écritureBloquée par le nœud le plus lentLocal uniquement — sous-millisecondes
Échec du lienLe site minoritaire devient en lecture seuleLes deux sites continuent en lecture/écriture
Quorum nécessaireOui (majorité des nœuds)Non
Cohérence des donnéesForte (tous les nœuds identiques)Éventuelle (brève latence de réplication)
Adapté aux liens satellitesNon (la latence nuit à la performance d'écriture)Oui (les files d'attente WAL se rattrapent)

Comment Cela Fonctionne

Flux de Réplication Logique

Modèle de Publication / Abonnement

Chaque site a :

  • Une publication qui diffuse tous les changements de table (sauf schema_migrations)
  • Une abonnement à la publication de chaque site pair

Mise en File d'Attente WAL Pendant une Panne de Lien

Lorsque le lien inter-site n'est pas disponible :

  1. Les écritures locales continuent sans interruption
  2. Les segments WAL s'accumulent du côté de la publication
  3. Le slot de réplication suit où chaque abonné s'est arrêté
  4. Lorsque le lien se rétablit, le WAL en file d'attente se rejoue depuis la dernière position reconnue
  5. Les deux sites convergent vers un état identique

La rétention WAL est limitée par max_slot_wal_keep_size pour éviter une croissance illimitée du disque pendant des pannes prolongées.

Prévention des Conflits

Les clés primaires UUID éliminent la principale source de conflits dans la réplication bidirectionnelle. Étant donné que chaque site génère des identifiants uniques globalement de manière indépendante, les opérations INSERT ne se chevauchent jamais.

L'option d'abonnement origin = none empêche les boucles de réplication — les changements arrivés par réplication ne sont pas republés à d'autres abonnés.

La table schema_migrations est exclue des publications car les deux sites exécutent des migrations identiques de manière indépendante.

Dernière Écriture Gagne pour l'État Dynamique

Les tables d'état dynamique (subscriber_state, pdn_session, lte_call) sont mises à jour fréquemment par le signalement Diameter — chaque ULR met à jour le MME de service, chaque CCR met à jour la session PGW, chaque AAR met à jour l'appel actif.

Dans un déploiement multi-sites, un abonné est servi par un site à la fois. Lorsque l'abonné se déplace entre les sites, les deux sites peuvent avoir des mises à jour de la même ligne subscriber_state à des moments différents. Sans résolution de conflit, l'ordre de réplication déterminerait quelle valeur survit — potentiellement en écrasant le MME de service actuel avec une valeur obsolète.

OmniHSS utilise des triggers Last-Write-Wins (LWW) sur les tables d'état dynamique :

CREATE TRIGGER lww_subscriber_state_trigger
BEFORE UPDATE ON subscriber_state
FOR EACH ROW
EXECUTE FUNCTION lww_subscriber_state();

Le trigger compare le timestamp updated_at de la mise à jour répliquée entrante avec la ligne existante. Si la ligne existante est plus récente, la mise à jour est silencieusement supprimée. Cela garantit :

  • Lorsque un abonné passe du Site A au Site B, la mise à jour plus récente du Site B l'emporte toujours
  • Les mises à jour obsolètes du Site A (d'avant le déplacement de l'abonné) sont rejetées
  • Les deux sites convergent vers la même valeur — la plus récente écriture

Tables avec triggers LWW :

TableMis à Jour ParFréquence
subscriber_stateULR, SAR, AIR, PURChaque mise à jour d'attachement/localisation
pdn_sessionCCR-I, CCR-TChaque création/suppression de session PDN
lte_callAAR, STRChaque configuration/démontage d'appel VoLTE

Les données de provisionnement statiques (abonnés, profils, clés, APNs) n'ont pas besoin de LWW — celles-ci ne sont mises à jour que par l'API de provisionnement, généralement à partir d'un seul plan de gestion.


Architectures de Déploiement

Site Unique (Pas de Réplication)

Plusieurs instances d'application HSS partagent une seule base de données PostgreSQL. La réplication de streaming PostgreSQL standard peut être utilisée pour un basculement de base de données local si nécessaire.

Déploiement à Deux Sites

Les deux sites sont des primaires complets. La provisionnement des abonnés sur n'importe quel site se réplique à l'autre. Chaque MME se connecte à son HSS local — il n'y a pas de dépendance Diameter inter-site.

Déploiement Multi-Sites

Chaque site s'abonne à la publication de chaque autre site. Les pairs sont auto-découverts à partir de l'inventaire Ansible — ajouter un site nécessite seulement de l'ajouter au groupe d'inventaire hss et d'exécuter le playbook.

Exigences Réseau

PortProtocoleObjectif
5432TCPConnexions client et de réplication PostgreSQL

Référence de Configuration

Variables Ansible

La réplication est configurée par groupe HSS dans votre inventaire :

hss:
hosts:
site-a-hss01:
ansible_host: 10.80.12.140
site-a-hss02:
ansible_host: 10.80.12.141
vars:
omnihss:
database_type: postgres
database_host: localhost
database_port: 5432
database_name: omnihss
database_username: omnihss
database_password: "secure_password"
replication:
enabled: true

Paramètres Ansible

ParamètreTypeRequisPar DéfautDescription
database_typeStringNonpostgresBackend de base de données. Doit être postgres pour la réplication.
database_hostStringNonlocalhostHôte PostgreSQL. Utilisez localhost lorsque Postgres s'exécute sur le même hôte qu'OmniHSS.
database_portEntierNon5432Port PostgreSQL.
database_nameStringNonomnihssNom de la base de données.
database_usernameStringOui-Utilisateur PostgreSQL. Doit avoir les privilèges CREATEDB et REPLICATION.
database_passwordStringOui-Mot de passe PostgreSQL.
replication.enabledBooléenNonfalseActiver la réplication logique bidirectionnelle. Lorsque true, le rôle Ansible configure automatiquement les publications, abonnements et entrées pg_hba.conf.

Découverte des Pairs

Les pairs sont découverts automatiquement à partir de deux sources :

  1. Groupe d'inventaire local : Tous les autres hôtes dans le groupe Ansible hss
  2. Sites distants : Entrées dans connected_sites.hss à partir de prod_master_peers.yml

Aucune configuration de pair par hôte n'est requise. Ajouter un hôte au groupe hss ou à connected_sites.hss et exécuter le playbook est suffisant.

Pairs de Sites Distants (prod_master_peers.yml)

Pour la réplication inter-site à travers des emplacements géographiques :

# group_vars/prod_master_peers.yml
connected_sites:
hss:
- remote-site-hss01: 10.80.20.140
- remote-site-hss02: 10.80.20.141

Configuration PostgreSQL

Le rôle Ansible configure automatiquement les paramètres PostgreSQL suivants lorsque la réplication est activée :

ParamètreValeurObjectif
wal_levellogicalRequis pour la réplication logique. Inclut les données complètes des lignes dans le WAL.
max_wal_senders10Maximum de processus d'envoi WAL simultanés (un par abonné).
max_replication_slots10Maximum de slots de réplication. Chaque pair utilise un slot.
listen_addresses*Accepter les connexions des sites pairs.

Le rôle ajoute également des entrées pg_hba.conf pour permettre les connexions de réplication à partir de chaque IP de pair découverte.


Gestion des Pairs

Ajout d'un Nouveau Site

  1. Ajoutez le(s) nouvel(s) hôte(s) au groupe d'inventaire hss, ou ajoutez-le à connected_sites.hss dans prod_master_peers.yml
  2. Exécutez le playbook OmniHSS

Le rôle va :

  • Installer PostgreSQL et OmniHSS sur le nouvel hôte
  • Exécuter les migrations de base de données
  • Créer une publication pour le nouveau site
  • Créer des abonnements à tous les pairs existants
  • Mettre à jour pg_hba.conf sur tous les pairs existants pour permettre le nouveau site
  • Créer des abonnements des pairs existants vers le nouveau site

Suppression d'un Site

ansible-playbook -i hosts site.yml --tags hss-remove-peer \
-e "peer_name=sydney confirm_remove=yes"

Le paramètre confirm_remove=yes est requis comme mesure de sécurité. Sans cela, le playbook refuse de continuer et affiche ce qui se passerait.

La suppression d'un pair :

  • Supprime l'abonnement (arrête la réplication entrante de ce pair)
  • Supprime l'IP du pair de pg_hba.conf
  • Les données déjà répliquées du pair restent dans la base de données locale
  • L'abonnement du site pair à ce site doit être supprimé séparément sur le pair

Ajout d'un Pair Ad-Hoc

Pour les cas où vous devez ajouter un pair en dehors du flux standard du playbook :

ansible-playbook -i hosts site.yml --tags hss-add-peer \
-e "peer_name=sydney peer_host=10.80.20.140"

Surveillance

Métriques Prometheus

Le service postgres_exporter s'exécute sur chaque hôte HSS sur le port 9187, exposant les métriques PostgreSQL à Prometheus.

Métriques de Réplication

MétriqueTypeDescription
pg_replication_slots_activeGauge1 si le slot de réplication est actif (pair connecté), 0 si inactif
pg_replication_slots_pg_wal_lsn_diffGaugeLatence de réplication en octets. Distance entre la position WAL actuelle et la dernière position confirmée du pair
pg_stat_replication_pg_current_wal_lsn_bytesGaugePosition WAL actuelle sur ce nœud

Exemples de Requêtes Prometheus

# Slot de réplication actif (1 = connecté, 0 = déconnecté)
pg_replication_slots_active{slot_name=~"sub_from_.*"}

# Latence de réplication en mégaoctets
pg_replication_slots_pg_wal_lsn_diff / 1048576

# Alerte : slot de réplication inactif pendant plus de 60 secondes
pg_replication_slots_active == 0

Alertes Recommandées

AlerteConditionSévéritéDescription
Slot de Réplication Inactifpg_replication_slots_active == 0 pendant 60sCritiqueLe pair est déconnecté. Le WAL s'accumule.
Latence WAL Excessivepg_replication_slots_pg_wal_lsn_diff > 104857600 pendant 5mAvertissementLa latence de réplication dépasse 100 Mo. Le pair peut être lent ou le lien dégradé.
Slot WAL PerduLe statut WAL est lostCritiqueLe slot a été invalidé. Le pair nécessite un re-seeding complet.

Validation Ansible

Le playbook OmniHSS valide la santé de la réplication à la fin de chaque exécution. Il vérifie :

  1. Tous les travailleurs d'abonnement sont en vie
  2. Tous les slots de réplication sont actifs
  3. La latence WAL est dans le seuil (100 Mo par défaut)
  4. Le statut du slot WAL est reserved ou extended (pas lost)

Si une assertion échoue, le playbook échoue avec un message d'erreur clair identifiant le problème.

Validation Manuelle

# Vérifiez que les travailleurs d'abonnement sont en vie
sudo -u postgres psql -d omnihss -c \
"SELECT subname, pid IS NOT NULL as worker_alive FROM pg_stat_subscription;"

# Vérifiez les slots de réplication et la latence
sudo -u postgres psql -d omnihss -c \
"SELECT slot_name, active,
pg_wal_lsn_diff(pg_current_wal_lsn(), confirmed_flush_lsn) as lag_bytes,
wal_status
FROM pg_replication_slots WHERE slot_type = 'logical';"

# Comparez les comptes d'abonnés entre les sites
sudo -u postgres psql -d omnihss -c "SELECT count(*) FROM subscriber;"

Dépannage

Travailleur d'Abonnement Mort

Symptômes : pg_stat_subscription montre pid IS NULL pour un abonnement. La validation Ansible échoue avec "Travailleurs morts."

Causes Courantes :

  • La table existe sur le publieur mais pas sur l'abonné (incompatibilité DDL)
  • Conflit de clé dupliquée d'un enregistrement inséré manuellement
  • Pair injoignable pendant une période prolongée causant l'invalidation du slot WAL

Résolution :

  1. Vérifiez les journaux PostgreSQL pour l'erreur spécifique :
    journalctl -u postgresql | grep "logical replication" | tail -20
  2. Si incompatibilité DDL : appliquez la migration manquante sur ce site, puis le travailleur redémarrera automatiquement
  3. Si clé dupliquée : résolvez le conflit manuellement, puis réactivez l'abonnement :
    ALTER SUBSCRIPTION sub_from_<pair> ENABLE;

Slot de Réplication Inactif

Symptômes : pg_replication_slots montre active = false. L'alerte Prometheus se déclenche.

Causes Courantes :

  • Problème de connectivité réseau entre les sites
  • PostgreSQL sur le site pair est arrêté
  • Pare-feu bloquant le port 5432 depuis l'IP du pair

Résolution :

  1. Vérifiez la connectivité réseau avec le pair :
    pg_isready -h <peer_ip> -U <db_user> -d omnihss
  2. Vérifiez que PostgreSQL sur le site pair est en cours d'exécution
  3. Vérifiez que les règles de pare-feu autorisent le port 5432 depuis l'IP de ce site

Le travailleur d'abonnement se reconnectera automatiquement lorsque le pair redeviendra joignable.

Slot WAL Perdu

Symptômes : pg_replication_slots montre wal_status = 'lost'. La validation Ansible échoue avec "WAL SLOT CRITIQUE."

Cause : Le pair a été déconnecté si longtemps que le WAL conservé a dépassé max_slot_wal_keep_size et a été nettoyé.

Résolution : Le pair nécessite un re-seeding complet :

  1. Supprimez l'abonnement cassé sur ce site :
    DROP SUBSCRIPTION sub_from_<pair>;
  2. Supprimez le slot cassé sur le site pair :
    SELECT pg_drop_replication_slot('sub_from_<this_site>');
  3. Réexécutez le playbook OmniHSS — il recréera l'abonnement avec copy_data = true pour effectuer une synchronisation initiale.

Latence WAL Excessive

Symptômes : pg_replication_slots_pg_wal_lsn_diff est grand et en croissance. L'alerte Prometheus se déclenche.

Causes Courantes :

  • Lien inter-site à haute latence ou congestionné
  • Site pair sous forte charge (le travailleur d'application ne peut pas suivre)
  • Grande opération en bloc (par exemple, provisionnement de masse) générant un volume WAL significatif

Résolution :

  1. Vérifiez si la latence est en croissance ou stable :
    SELECT slot_name,
    pg_wal_lsn_diff(pg_current_wal_lsn(), confirmed_flush_lsn) as lag_bytes
    FROM pg_replication_slots WHERE slot_type = 'logical';
  2. Si stable : le pair applique des changements mais est en retard. Il rattrapera.
  3. Si en croissance : enquêtez sur le lien réseau ou la charge du site pair.
  4. Pour les opérations en bloc : la latence pendant l'opération est attendue et se résoudra après la fin de l'opération.

Coordination des Migrations de Schéma

Important : Les changements de schéma de base de données (migrations) ne se répliquent pas via la réplication logique. Lors du déploiement d'une nouvelle version d'OmniHSS qui inclut des changements de schéma :

  1. Appliquez la migration sur tous les sites avant de déployer le code de l'application qui dépend des nouvelles colonnes/tables
  2. Le playbook Ansible gère cela automatiquement — il exécute des migrations sur chaque hôte
  3. Si vous déployez manuellement, exécutez les migrations sur tous les sites d'abord :
    /opt/omnihss/bin/hss rpc "Hss.Command.Database.migrate()"