Points Clés
- La plupart des bibliothèques de consensus (Raft, Paxos) traitent la machine d'état comme une boîte noire pure.
- Si un leader tombe en panne après l'effet de bord mais avant de le valider, des doublons se produisent.
- Chr2 utilise une Boîte aux Lettres Répliquée : les effets de bord sont stockés comme 'en attente' dans l'état répliqué.
- Le Durcissement Durable utilise un manifeste persisté via une séquence atomique tmp+fsync+rename pour arrêter les leaders zombies.
- Chr2 est un système CP, privilégiant la sécurité avant la disponibilité.
Résumé Rapide
Les bibliothèques de consensus standard comme Raft et Paxos ignorent généralement ce qui se passe après qu'une entrée de journal a été validée. Elles traitent la machine d'état comme une boîte noire, supposant que l'application gère le reste. Cette hypothèse s'effondre lorsque l'application doit déclencher des actions externes, telles que facturer une carte de crédit, déclencher un webhook ou envoyer un email. Si un leader tombe en panne après avoir effectué l'action mais avant que la validation ne soit finalisée, le système perd souvent la trace de l'opération. Lorsqu'un nouveau leader prend le relais, il peut ré-exécuter la même commande, conduisant à des effets de bord dupliqués.
Pour résoudre cela, une nouvelle bibliothèque nommée Chr2 a été développée pour traiter les effets de bord sécurisés contre les pannes comme une fonctionnalité principale plutôt qu'une réflexion tardive. La philosophie centrale est de s'assurer que les effets de bord ne sont pas seulement journalisés mais gérés via un cycle de vie d'exécution strict. La bibliothèque introduit un mécanisme de Boîte aux Lettres Répliquée. Au lieu de s'exécuter immédiatement, les effets de bord sont stockés comme des éléments 'en attente' au sein de l'état répliqué. L'exécution est strictement contrôlée ; seul le leader actif est autorisé à exécuter ces effets, et il doit le faire sous un jeton de durcissement spécifique.
Empêcher les 'leaders zombies' — d'anciens leaders qui reviennent en ligne et tentent d'agir — est crucial. Chr2 utilise le Durcissement Durable pour gérer cela. Un fichier manifeste persiste le numéro de vue le plus élevé en utilisant des opérations atomiques (tmp+fsync+rename). Cela garantit qu'un ancien leader ne peut pas se réveiller et exécuter des effets obsolètes. Pour garantir la cohérence lors de la récupération ou de la lecture, le système fournit un Contexte Déterministe. Le code de l'application reçoit une graine déterministe de Générateur de Nombres Aléatoires (RNG) et l'heure du bloc directement depuis le journal, assurant que la lecture du journal produit des transitions d'état identiques. Enfin, le Journal d'Avant-Écriture (WAL) est strict : les entrées sont vérifiées par CRC et chaînées par hachage. Si une corruption est détectée, le système est conçu pour s'arrêter plutôt que de deviner. Bien que ces mesures offrent une sécurité robuste, le système est explicitement conçu comme un système CP (Consistance/Tolérance aux Partitions), privilégiant la sécurité avant la disponibilité et acceptant que les effets de bord seront au moins une fois plutôt que strictement exactement une fois.
Le Problème avec le Consensus Standard
Les algorithmes de consensus sont la colonne vertébrale des systèmes distribués, permettant à plusieurs serveurs de s'accorder sur une séquence de commandes. Les bibliothèques implémentant Raft et Paxos sont largement utilisées à cette fin. Cependant, ces bibliothèques se concentrent généralement uniquement sur la réplication du journal et la cohérence. Elles garantissent que tous les nœuds s'accordent sur l'ordre des opérations, mais elles ne gèrent pas les conséquences de ces opérations. Cela est souvent décrit comme le traitement de la machine d'état comme une 'boîte noire'. La couche de consensus passe la commande à la couche d'application et considère son travail comme terminé.
Cette séparation des préoccupations devient problématique lorsque l'application doit interagir avec le monde extérieur. Les opérations courantes incluent :
- Facturer la carte de crédit d'un client.
- Envoyer une notification par email.
- Déclencher un webhook vers un service externe.
Le danger survient lors d'une panne du leader. Imaginez qu'un leader reçoit une commande de 'Facturer 50 €'. Il la transmet à l'application, qui contacte la passerelle de paiement et facture avec succès la carte. Cependant, avant que le leader puisse répliquer l'entrée de journal à une majorité de followers et la valider, il tombe en panne. Les followers ne savent pas que l'opération a été terminée. Lorsqu'un nouveau leader est élu, il voit l'entrée non validée et l'exécute à nouveau. Le client est facturé deux fois. C'est le 'mensonge' de l'exécution exactement une fois mentionné dans la documentation : garantir une véritable exécution exactement une fois au niveau du consensus est incroyablement difficile sans l'aide de l'application ou d'un mécanisme spécialisé.
Comment Chr2 Assure la Sécurité contre les Pannes
Chr2 aborde le problème en intégrant la gestion des effets de bord directement dans le mécanisme de consensus. Il s'éloigne du modèle de boîte noire vers un système où les effets de bord sont des citoyens de première classe. La bibliothèque atteint cela grâce à une combinaison de quatre mécanismes techniques spécifiques conçus pour fonctionner ensemble.
Boîte aux Lettres Répliquée
Le changement fondamental dans Chr2 est l'introduction d'une Boîte aux Lettres Répliquée. Plutôt que d'exécuter un effet de bord immédiatement et d'espérer que l'entrée de journal soit validée, Chr2 stocke l'intention comme un état 'en attente' dans le journal répliqué. Cela signifie que la demande d'exécution d'une action est répliquée sur d'autres nœuds comme tout autre changement d'état. Cependant, l'exécution réelle est découplée de l'entrée de journal initiale. Seul le leader désigné est autorisé à exécuter ces effets en attente, et il le fait sous la protection d'un jeton de durcissement. Ce jeton agit comme une preuve d'autorité, garantissant que seul le leader valide actuel peut déclencher des actions externes.
Durcissement Durable et Prévention des Zombies
Un risque important dans les systèmes distribués est le 'leader zombie'. Cela se produit lorsqu'un leader est partitionné du réseau, présumé mort, puis réapparaît soudainement. S'il croit toujours être le leader, il pourrait tenter d'exécuter des opérations qui ont déjà été gérées par son successeur. Chr2 prévient cela en utilisant le Durcissement Durable.
Le système maintient un fichier manifeste qui enregistre le numéro de 'vue' le plus élevé (essentiellement le mandat du leader). Lorsqu'un leader change, ce manifeste est mis à jour en utilisant une séquence d'opérations spécifique : écriture dans un fichier temporaire, forçage de la synchronisation sur le disque (fsync), puis renommage du fichier vers le nom final (remplacement atomique). Cela garantit que même si l'alimentation est coupée pendant la mise à jour, l'état reste cohérent. Un ancien leader tentant de se réveiller trouvera que son numéro de vue est inférieur à celui du manifeste persisté et refusera d'exécuter des effets.
Contexte Déterministe pour la Lecture
La lecture du journal est une exigence standard pour la récupération après des pannes. Cependant, les effets de bord reposent souvent sur des variables comme les horodatages ou les nombres aléatoires. Si ceux-ci changent pendant la lecture, la machine d'état peut se retrouver dans un état différent d'avant. Chr2 résout cela en fournissant un Contexte Déterministe. Lorsque le code de l'application doit effectuer une action, il reçoit des entrées spécifiques de la couche de consensus :
- Une graine déterministe de Générateur de Nombres Aléatoires (RNG).
- L'heure de bloc exacte depuis le journal.
Parce que ces entrées sont fixées par l'historique du journal, la lecture du journal produira toujours le même résultat. Cela garantit des transitions d'état 1:1.
Journal d'Avant-Écriture (WAL) Strict
L'intégrité des données est primordiale. Chr2 utilise un WAL Strict. Chaque entrée écrite dans le journal est protégée par un CRC (Cyclic Redundancy Check) et chaînée par hachage à l'entrée précédente. Cela crée une chaîne de données vérifiable. Si une corruption est détectée au milieu du journal, le système est conçu pour s'arrêter immédiatement plutôt que d'essayer de deviner ce que les données manquantes auraient pu être. Cette approche 'défaut fermé' empêche la corruption des données de se propager à travers le système.
Les Compromis
Chr2 est un système CP (Consistance/Tolérance aux Partitions). Cela signifie qu'il privilégie la sécurité (consistance) avant la disponibilité. En cas de panne réseau ou de partition, le système refusera de traiter de nouvelles requêtes pour garantir qu'aucun effet de bord dupliqué ou incohérent ne se produise. C'est un choix de conception délibéré : il est préférable d'avoir un système indisponible temporairement que de faire payer les clients deux fois ou d'envoyer des emails indésirables.
Le système accepte également des effets de bord au moins une fois. Cela signifie qu'il garantit qu'un effet de bord sera exécuté au moins une fois, mais il peut parfois en exécuter plus d'une (bien que le mécanisme de boîte aux lettres répliquée et de durcissement rende cela extrêmement rare et contrôlé). Pour obtenir une garantie stricte exactement une fois, le système qui reçoit l'effet de bord (le système de paiement, le serveur SMTP, etc.) doit implémenter sa propre déduplication basée sur l'ID de l'effet de bord.




