Réalité des systèmes distribués¶
Les pannes ne sont pas des exceptions — ce sont la norme. Concevoir pour la panne est la seule stratégie viable.
Les fallacies du distribué¶
Peter Deutsch a formalisé huit illusions que les développeurs acceptent implicitement quand ils conccoivent des systèmes distribués. Chaque postulat est faux, et chaque violation produit des défaillances spécifiques :
| Fallacy | Réalité | Conséquence architecturale |
|---|---|---|
| Le réseau est fiable | Les paquets se perdent, les connexions sont coupees | Retry, circuit breaker, idempotence obligatoire |
| La latence est nulle | Un appel réseau prend 1000x plus qu'un appel local | Timeouts, deadline propagation, appels asynchrones |
| La bande passante est infinie | Les liens saturent, surtout entre zones et regions | Pagination, compression, cache local |
| Le réseau est sécurisé | Chaque segment est une surface d'attaque | mTLS, chiffrement en transit, zero trust |
| La topologie ne change pas | Les pods redemarrent, les IPs changent, les routes evoluent | Service discovery, DNS dynamique |
| Il n'y a qu'un seul administrateur | Plusieurs équipes, plusieurs fournisseurs, plusieurs zones | Conventions, observabilité partagee, contrats |
| Le transport est sans coût | Chaque appel réseau coute en CPU, mémoire et latence | Batching, cache, réduction des appels |
| Le réseau est homogène | Mix de protocoles, versions, capacités | Adapter pattern, versionning d'API |
Autant de postulats faux qui conduisent à des architectures fragiles quand ils ne sont pas pris en compte des la conception. Quand le réseau flanche (et il flanchera), quand un pod redemarrera au pire moment, quand la base de données sera lente pendant 30 secondes — le système doit survivre.
Modes de défaillance¶
Tous les échecs ne se ressemblent pas. La taxonomie des modes de défaillance aide à classifier les pannes et a choisir les mécanismes de protection adaptés.
Crash failure¶
Le composant s'arrêté complètement et ne répond plus. C'est le mode le plus simple à détecter et a gérer. Un processus qui meurt, un conteneur tue par l'OOM killer, un serveur qui s'éteint.
Détection : heartbeat, health check liveness. Protection : redondance, redémarrage automatique, replicas.
Omission failure¶
Le composant omet de traiter certains messages. Il est vivant mais perd des requêtes ou des réponses. Un serveur qui droppe des connexions sous charge, un broker qui perd des messages non acquittes.
Détection : monitoring du taux de réponse, correlation requêtes envoyees / réponses reçues. Protection : retry avec idempotence, acknowledgment explicite, at-least-once delivery.
Timing failure¶
Le composant répond, mais pas dans le délai attendu. Un service qui répond en 30 secondes au lieu de 200ms, une base de données qui ralentit sous charge.
Détection : monitoring des percentiles de latence (p95, p99), timeouts. Protection : deadline propagation, circuit breaker, backpressure.
Response failure¶
Le composant répond, mais avec une réponse incorrecte. Des données corrompues, un calcul faux, une réponse partielle présentée comme complète.
Détection : validation des réponses, checksums, tests de cohérence. Protection : vérification côté appelant, reconciliation périodique, idempotency keys.
Byzantine failure¶
Le composant se comporte de manière arbitraire et imprévisible. Il peut envoyer des réponses contradictoires a différents appelants, mentir sur son état, ou altérer les données en transit.
Détection : extremement difficile. Consensus distribué, signatures cryptographiques. Protection : protocoles BFT (Byzantine Fault Tolérance), quorum, vérification multi-source.
graph LR
A[Crash] -->|plus simple| B[Omission]
B --> C[Timing]
C --> D[Response]
D -->|plus complexe| E[Byzantine]
style A fill:#2a9d8f,color:#fff
style B fill:#2a9d8f,color:#fff
style C fill:#e9c46a,color:#000
style D fill:#e76f51,color:#fff
style E fill:#c44,color:#fff En pratique, la grande majorité des pannes en production sont des crash, omission ou timing failures. Les défaillances byzantines sont rares dans les systèmes internes (mais pertinentes dans les systèmes ouverts comme les blockchains).
Le théorème CAP et ses implications pratiques¶
Le théorème CAP etablit qu'un système distribué ne peut garantir simultanément que deux des trois propriétés suivantes :
Consistency — tous les nœuds voient la même donnée au même moment. Une lecture retourné toujours la dernière écriture.
Availability — chaque requête reçoit une réponse (succès ou échec), même en cas de panne partielle.
Partition tolérance — le système continue de fonctionner même quand la communication entre certains nœuds est interrompue.
Le choix est binaire pendant une partition¶
Les partitions réseau arrivent. Ce n'est pas une question de "si" mais de "quand". Pendant une partition, le système doit choisir :
-
CP (Consistency + Partition tolérance) — refuser de répondre plutôt que retourner une donnée potentiellement obsolète. Les écritures sont bloquees jusqu'à résolution de la partition. Exemples : ZooKeeper, etcd, systèmes bancaires critiques.
-
AP (Availability + Partition tolérance) — continuer a répondre avec des données potentiellement obsolètes. Les conflits sont resolus après la partition (eventual consistency). Exemples : Cassandra, DynamoDB, DNS.
graph TD
CAP["Theoreme CAP"]
CAP --> CP["CP : Consistency + Partition\nRefuse de repondre si incertain\nex: etcd, ZooKeeper"]
CAP --> AP["AP : Availability + Partition\nRepond toujours, meme obsolete\nex: Cassandra, DNS"]
CAP --> CA["CA : Consistency + Availability\nImpossible en distribue reel\n(pas de partition tolerance)"]
style CP fill:#264653,color:#fff
style AP fill:#2a9d8f,color:#fff
style CA fill:#999,color:#fff Au-delà de CAP : le modèle PACELC¶
Le modèle PACELC affine CAP en posant la question : même en l'absence de partition (fonctionnement normal), il faut choisir entre latence et consistency.
PACELC : si Partition, choisir entre Availability et Consistency. Else (fonctionnement normal), choisir entre Latency et Consistency.
| Système | Pendant partition (PAC) | Fonctionnement normal (ELC) | Profil |
|---|---|---|---|
| DynamoDB | AP | EL (latence faible) | AP/EL |
| Cassandra | AP | EL (latence faible) | AP/EL |
| MongoDB | CP | EC (consistance forte) | CP/EC |
| Spanner | CP | EC (consistance forte) | CP/EC |
| CockroachDB | CP | EL (compromis) | CP/EL |
Implications architecturales concrètes¶
Le choix CP vs AP est rarement global. Dans un même système, certaines données exigent la consistance forte (solde bancaire, stock d'un produit limite), d'autres tolèrent la consistance à terme (compteur de vues, cache de profil utilisateur).
L'architecture doit classifier les données par exigence de consistance et appliquer des stratégies différentes :
- Forte consistance — opérations financieres, reservations avec stock limite, sequences d'identifiants
- Consistance à terme acceptable — catalogue produit, profils utilisateur, statistiques, cache
- Lecture locale / écriture centralisee — configuration, référence data, feature flags
Tip
Ne cherchez pas a rendre tout consistant. Le coût de la consistance forte est la latence et la disponibilité réduite pendant les partitions. Identifiez les données critiques qui l'exigent vraiment et acceptez la consistance à terme pour le reste. Cette classification est une décision d'architecture, pas un détail d'implémentation.
Partitions réseau en pratique¶
Les partitions réseau ne sont pas un concept théorique. Elles arrivent régulièrement dans les environnements cloud multi-zones :
- Split-brain — deux partitions du cluster continuent d'opérer independamment, chacune croyant être le cluster principal. Produit des écritures conflictuelles.
- Asymetric partition — le nœud A peut joindre B, mais B ne peut pas joindre A. Le plus traitre car les health checks unidirectionnels ne le detectent pas.
- Partial partition — seuls certains nœuds sont isoles. Le cluster est fragmente en plus de deux groupes.
Stratégies de protection¶
Quorum — exiger qu'une majorité de nœuds (N/2 + 1) soit d'accord avant d'accepter une écriture. La partition minoritaire se met en read-only ou refuse les écritures.
Fencing tokens — chaque leader obtient un jeton monotone croissant. Un ancien leader qui revient après une partition ne peut pas écrire avec un jeton perime.
Lease-based leadership — le leader detient un bail temporaire. Si le bail expire sans renouvellement (partition réseau), un nouveau leader est elu. L'ancien leader cesse d'écrire à l'expiration de son bail.
Lien avec les fondations réseau¶
Les mécanismes de fiabilité décrits ici s'appuient sur la comprehension des couches réseau présentées au chapitre 01 (fondations). La latence réseau, la perte de paquets, le fonctionnement de TCP (retransmission, congestion window) et de DNS (TTL, cache, résolution) sont les primitives sur lesquelles on construit retry, timeout et circuit breaker.
Un retry qui fonctionne bien suppose de comprendre que TCP a déjà ses propres mécanismes de retransmission. Un timeout bien calibre suppose de connaître la latence typique du réseau entre les zones. Une deadline propagation efficace suppose de comprendre comment les headers HTTP traversent les proxies et load balancers.
La fiabilité applicative ne remplacé pas la fiabilité réseau — elle la complète en ajoutant une couche de protection au niveau ou l'application peut prendre des décisions informees (fallback, circuit ouvert, dégradation gracieuse).
Chapitre suivant : Circuit breaker et bulkhead — protéger le système contre la propagation des pannes.