Les systèmes distribués modernes sont une question de compromis. Les performances, la fiabilité, l'évolutivité et la cohérence ont un prix : il faut toujours payer un prix quelque part. C'est là qu'intervient le théorème CAP : c'est le point de départ pour comprendre les compromis inévitables dans la conception distribuée.
Pourquoi le théorème CAP est-il vrai ? Qu'explique-t-il réellement ? Et, plus important encore, est-il suffisant ? Dans cet article, nous explorerons le théorème CAP, ses limites, les critiques auxquelles il a été confronté et la manière dont de nouvelles idées comme PACELC font avancer le débat. Plongeons-nous dans le vif du sujet.
La première version du théorème CAP a débuté par un débat entre ACID et BASE . Mais au fil du temps, il a évolué, a obtenu une preuve formelle et est devenu le théorème CAP tel que nous le connaissons aujourd'hui.
Le théorème CAP stipule qu'un système distribué peut satisfaire au plus deux des trois propriétés simultanément :
Cette limitation oblige les ingénieurs à faire des compromis difficiles en fonction des objectifs du système et des réalités de leurs environnements distribués.
La cohérence dans CAP n'est pas la même que la cohérence dans les transactions ACID . Dans le théorème CAP, elle fait référence à la linéarisation ou à la cohérence forte . Cela signifie que tous les nœuds d'un système distribué doivent toujours présenter une vue unique et à jour des données , quel que soit le nœud qui traite la requête. Cela signifie que chaque opération de lecture reflète l'écriture la plus récente, quel que soit le nœud que vous interrogez.
💡 La cohérence dans ACID, en revanche, vise à garantir qu'une transaction amène la base de données d'un état valide à un autre état valide, en suivant les règles définies par le schéma de la base de données. Il s'agit plutôt d'appliquer des contraintes d'intégrité (comme les clés étrangères, les contraintes uniques, etc.) et de garantir que la base de données ne reste pas dans un état non valide, même en cas de panne.
La disponibilité dans CAP signifie que chaque nœud non défaillant doit renvoyer une réponse pour chaque requête qu'il reçoit, quelles que soient les partitions réseau . En d'autres termes, si un nœud sain reçoit une requête, il doit la traiter et y répondre. Cependant, CAP ne garantit pas que la réponse sera toujours « correcte » ou à jour . Il garantit simplement que le nœud ne tombe pas en panne silencieusement (par exemple, dans un système AP, les nœuds peuvent répondre avec des données obsolètes lors d'une partition pour garantir la disponibilité).
💡 Eric Brewer (l'auteur original de CAP) a décrit à l'origine cette propriété de manière un peu plus flexible comme suit : « presque toutes les requêtes devraient obtenir une réponse ». Cependant, dans la preuve formelle de CAP, la disponibilité a été rendue plus stricte, exigeant que « chaque requête reçoive une réponse tant que le nœud qui la gère est sain ».
En pratique, la disponibilité n'est pas une garantie absolue : elle dépend souvent de contraintes spécifiques au système, comme le temps que vous êtes prêt à attendre une réponse. Pour les systèmes réels, le temps de réponse (ou les délais d'attente) joue un rôle essentiel dans la définition de votre SLA (accord de niveau de service), même si le CAP lui-même ne tient pas directement compte de la latence. Plus d'informations à ce sujet dans cet article de blog .
La tolérance de partitionnement consiste à survivre aux pannes du réseau. Si les nœuds ne peuvent pas communiquer en raison d'une division du réseau (partition), le système doit toujours respecter ses garanties de cohérence ou de disponibilité, en fonction de ses choix de conception. Une partition se produit lorsque les nœuds ne peuvent pas communiquer en raison de paquets abandonnés, de délais d'attente ou de divisions du réseau.
Les systèmes distribués ne vivent pas dans un monde de conte de fées avec des réseaux parfaits. Des paquets sont perdus, des dépassements de délai se produisent et des pics de latence sont inévitables. Pour cette raison, la tolérance de partition n'est pas négociable dans tout système distribué : les partitions se produiront tôt ou tard, vous ne pouvez donc pas « choisir » de les ignorer, aussi tentant que cela puisse paraître.
Dans CAP, la tolérance de partition ne signifie pas que le système continue de fonctionner comme si de rien n'était. Cela signifie que le système doit décider s'il doit donner la priorité à la disponibilité (AP) ou à la cohérence (CP) pendant une partition. Si vous deviez ignorer la tolérance de partition, vous construiriez essentiellement un système monolithique non distribué.
La façon la plus simple de comprendre le CAP est d'envisager une partition réseau , une situation dans laquelle deux parties d'un système distribué ne peuvent pas communiquer entre elles. Dans un tel scénario, le système est confronté à trois résultats possibles :
Ainsi, lors d'une partition , le système ne peut satisfaire que deux des trois propriétés (C, A ou P) . Une fois la partition résolue (c'est-à-dire que les nœuds interagissent à nouveau), le système peut retrouver les trois propriétés, mais lors de la partition elle-même , des compromis sont inévitables.
Une conséquence du théorème pour les systèmes asynchrones est que seules trois combinaisons de cohérence, de disponibilité et de tolérance de partition sont possibles :
Les systèmes de ce type répondent aux requêtes, mais les données renvoyées ne sont pas toujours à jour, les mises à jour des données étant plus lentes mais « toujours » disponibles. DNS, DynamoDB et Cassandra sont des exemples de tels systèmes.
Les systèmes de ce type renvoient toujours des données à jour, mais certains nœuds, voire tous, du système peuvent ne pas répondre s'ils sont partitionnés. Cela donne des mises à jour atomiques mais peut entraîner des dépassements de délai. Les bases de données NoSQL telles que Google BigTable, MongoDB, HBase et Redis sont toutes des systèmes de ce type.
Les systèmes de ce type renvoient toujours des données à jour lorsqu'il n'y a pas de partitions. En raison de cette dernière limitation, ces systèmes ne sont généralement utilisés que sur une seule machine. Les bases de données relationnelles classiques en sont un exemple.
En réalité, nous choisissons entre CP et AP car CA est fondamentalement un monolithe sans partitions. Pour les systèmes à grande échelle, les concepteurs ne peuvent pas abandonner P et ont donc un choix difficile entre C et A.
Dans CA, la défaillance d'un nœud signifie l'indisponibilité totale du service. Mais cela ne désactive pas l'évolutivité, car nous pouvons cloner des monolithes indépendants et répartir la charge sur eux.
Le théorème CAP est un concept fondamental dans les systèmes distribués, mais il n'est pas sans limites. Malgré toute sa clarté dans la présentation de l'idée de compromis, le théorème CAP a souvent été critiqué pour avoir trop simplifié des réalités complexes, ce qui a conduit à des malentendus et à des applications erronées.
L'une des critiques les plus courantes est que les compromis du théorème CAP (choix entre cohérence (C) et disponibilité (A)) ne s'appliquent que lorsqu'une partition du réseau (P) se produit réellement. En fonctionnement normal, lorsque le réseau est stable et qu'aucune partition n'existe, il n'y a pas de compromis inhérent entre cohérence et disponibilité.
De plus, ces compromis ne sont pas universels dans l'ensemble du système. Au sein d'un même système distribué :
Cette nuance est souvent perdue dans les discussions de haut niveau sur le CAP, ce qui conduit à des classifications trop simplifiées des systèmes en « CP » ou « AP » dans leur ensemble.
Une autre critique importante est que le théorème CAP ne tient pas compte de la latence , même si la latence et le partitionnement sont profondément liés dans la pratique. Par exemple :
Dans les systèmes distribués réels, lorsqu'une partition ou une latence élevée se produit, le système doit prendre une décision dans un délai d'attente : donner la priorité à la disponibilité en renvoyant un résultat potentiellement obsolète, ou donner la priorité à la cohérence en attendant plus longtemps (et en ne répondant potentiellement pas). La vue binaire de CAP ne capture pas la complexité de ces décisions.
Le théorème CAP présente la cohérence, la disponibilité et la tolérance de partition comme des propriétés binaires : soit vous les avez, soit vous ne les avez pas. Mais en pratique, ces trois propriétés existent sur un spectre :
Cette nature continue des propriétés rend le CAP trop simpliste pour modéliser les complexités des systèmes distribués modernes.
Bien que le modèle CAP ait révolutionné notre compréhension des compromis dans les systèmes distribués, il ne s'agit pas du dernier mot sur le sujet. Le théorème PACELC décrit par Daniel J. Abadi est considéré comme une approche alternative à la conception de systèmes distribués. Il est basé sur le modèle CAP, mais en plus de la cohérence, de la disponibilité et de la tolérance de partition, il inclut également la latence et l'exclusion logique entre les combinaisons de ces concepts.
PACELC introduit deux modes de fonctionnement distincts pour les systèmes distribués :
Bien que les partitions soient inévitables dans les systèmes distribués, elles sont rares par rapport aux défis qui se posent pendant le fonctionnement normal. Dans les systèmes distribués modernes, la latence constitue souvent un goulot d'étranglement plus important que les partitions réseau, en particulier pour les applications à l'échelle mondiale. C'est là que PACELC se concentre, en abordant les compromis qui se produisent lorsque le système fonctionne sans partitions. Contrairement à CAP, qui se concentre uniquement sur le comportement lors de scénarios de défaillance, PACELC met l'accent sur les décisions que les architectes doivent prendre chaque jour pour équilibrer la latence (L) et la cohérence (C) :
En étendant la conversation au-delà des partitions pour inclure le fonctionnement normal, PACELC garantit que les performances quotidiennes des systèmes distribués sont traitées avec l’importance qu’elles méritent.
La formulation du théorème CAP a été un événement important dans la communauté, et les études sur son impact sur la conception des systèmes distribués ont montré que les concepteurs de systèmes distribués ne devraient pas limiter le système à deux propriétés - ils devraient s'efforcer de maximiser les garanties requises dans chaque cas particulier. À cette fin, il est raisonnable de diviser le système en segments, chacun ayant ses propres exigences, et de concevoir le système en fonction des exigences de chacun des segments.
Le théorème CAP est depuis des décennies une pierre angulaire de la réflexion sur les systèmes distribués. Il nous a fourni un cadre pour raisonner sur les compromis inhérents à la cohérence, à la disponibilité et à la tolérance de partition. Mais à bien des égards, il s'agit d'une simplification de la réalité, supposant des choix binaires et ignorant des facteurs critiques comme la latence.
PACELC s'appuie sur le CAP, reconnaissant que :
CAP et PACELC sont tous deux des outils précieux, mais aucun des deux ne constitue une recette étape par étape pour la création de systèmes. Au contraire, ils fournissent des modèles mentaux permettant d'évaluer les compromis et de comprendre les limites des architectures distribuées.
Merci de votre lecture !
Vous êtes curieux de quelque chose ou vous avez des idées à partager ? Laissez votre commentaire ci-dessous ! Consultez mon blog ou suivez-moi via LinkedIn , Substack , ou Telegram .