Aller au contenu principal

Le théorème CAP

Ce que ce chapitre apporte 6 points
  • Énoncer les propriétés ACID et dire ce que chacune garantit.
  • Définir une partition réseau et la distinguer d'une panne.
  • Énoncer correctement le théorème CAP, et repérer les formulations fautives.
  • Décrire les propriétés BASE et la cohérence à terme.
  • Calculer si un réglage de quorum garantit ou non la lecture de la dernière écriture.
  • Choisir un compromis à partir du besoin métier plutôt que de la mode technique.

Une base sur une seule machine tient une promesse simple : ce qui vient d'être écrit sera lu. Répartir les données sur plusieurs machines rend cette promesse coûteuse, et un jour impossible. Le théorème CAP dit exactement quand, et il est presque toujours cité de travers. Il n'oblige à renoncer à rien tant que le réseau fonctionne ; il impose un choix pendant les quelques secondes où il ne fonctionne plus.

Le chapitre précédent a réparti les données sur des machines qui tombent en panne, et a réglé la question de la durabilité : avec trois copies, rien n'est perdu. Il a laissé de côté une question plus difficile. Quand une donnée existe en trois exemplaires et qu'une écriture arrive, que lit celui qui interroge la deuxième copie avant qu'elle ne soit à jour ?

Cette question n'a pas de bonne réponse universelle. Elle a des réponses, chacune payée d'un prix connu, et le rôle du concepteur est de choisir lequel.

Ce que garantit une transaction

Les propriétés ACID

Atomicité. Une transaction s'applique en entier ou pas du tout. Un virement ne peut pas débiter sans créditer.

Cohérence. Une transaction fait passer la base d'un état valide à un autre état valide, au sens des contraintes déclarées : clés étrangères, unicité, vérifications.

Isolation. Deux transactions simultanées ne se gênent pas plus que ce que le niveau d'isolation choisi tolère ; au niveau le plus strict, le sérialisable, elles produisent le même résultat que si elles s'étaient exécutées l'une après l'autre.

Durabilité. Une transaction validée survit à une coupure de courant.

Ces quatre propriétés sont l'acquis du chapitre sur les transactions du parcours Bases de données, et elles ont un coût qui ne se voit pas sur une machine unique : elles exigent une coordination. L'isolation impose des verrous ou un contrôle de version ; la durabilité impose une écriture réellement descendue sur le disque avant de répondre.

Cette coordination se voit sur la dernière place d'un spectacle. Deux guichets la vendent au même moment : chacun lit le nombre de places restantes, trouve 1, vend un billet et écrit ce qu'il a lu moins un. Dans la figure, écrire places = lu - 1 écrit la dernière valeur que le guichet a lue, moins un, comme le double retrait du chapitre sur les transactions ; toute écriture pose sur places un verrou tenu jusqu'à la validation.

niveau d'isolation
comportement
Au niveau sérialisable, une transaction dont une lecture ne tient plus est refusée à sa validation : un moyen parmi ceux que la norme permet.
guichet Aen attente
  1. ▸ début
  2.   lire places
  3.   écrire places = lu - 1
  4.   valider
la base
places
1
valeur validée
guichet Ben attente
  1. ▸ début
  2.   lire places
  3.   écrire places = lu - 1
  4.   valider
Rien ne s'est encore passé. Avancer les guichets dans l'ordre de son choix.
La dernière place d'un spectacle, vendue par deux guichets au même moment. Avancer en alternance stricte, A puis B, jusqu'au bout, et relever le nombre de places restantes.
À manipuler
Avancer A et B en alternance stricte, au niveau « lecture validée » : au sixième pas, B attend le verrou de A ; dès que A valide, B écrit 1 - 1 = 0, et sa validation est marquée « mise à jour perdue ». Valeur finale : places = 0, pour deux billets vendus.
Rejouer le même ordre en « lecture non validée » puis en « lecture répétable » : la vente se perd de la même façon.
Passer au niveau « sérialisable » et rejouer : quand B valide à son tour, la figure refuse sa validation, places = 0, et un seul billet est vendu.
Au même niveau, choisir le comportement « de MySQL » et rejouer l'alternance : au cinquième pas, A attend le verrou partagé de B ; au sixième, MySQL annule B par un interblocage, et places = 0.
Avancer A jusqu'au bout avant de commencer B : B lit 0 et écrit -1, sans qu'aucune anomalie soit signalée.

Entrelacées, les deux ventes laissent places à 0 : deux billets vendus, un seul décompté. Une contrainte qui interdit un nombre de places négatif, le C d'ACID, n'y voit rien, puisque 0 la respecte ; c'est en série qu'elle aurait servi, en refusant la seconde vente, celle qui écrit -1. Ce qui protège ici est l'isolation à son niveau le plus strict : le refus de la validation de B, ou, sous MySQL, l'interblocage qui annule B. L'un comme l'autre supposent une base unique, qui voit les deux ventes. Que les deux guichets écrivent sur deux copies séparées par une coupure du réseau, et chaque copie lit 1 sans pouvoir apprendre que l'autre vend : pour ne vendre qu'un billet, l'une des deux doit attendre le retour du réseau ou refuser la vente, donc renoncer à répondre ; pour répondre tout de suite, chacune vend, et la place part deux fois. Ce choix entre attendre et répondre est celui que pose le théorème CAP, plus bas, et l'exercice type 4 dit comment le trancher pour une réservation.

Le C d'ACID et le C de CAP ne désignent pas la même chose

Le C d'ACID signifie que les contraintes déclarées sont respectées : pas de clé étrangère orpheline, pas de doublon sur une clé unique. C'est une propriété de chaque transaction, que le chapitre sur les transactions montre sur un virement.

Le C de CAP signifie que toutes les copies répondent la même chose au même instant, c'est-à-dire que le système se comporte comme s'il n'en existait qu'une.

Un système peut respecter l'un sans l'autre. La confusion des deux est la source d'une bonne moitié des affirmations fausses sur le sujet.

Ce qu'est une partition

Partition réseau

Il y a partition quand des machines du système ne peuvent plus communiquer entre elles, alors qu'elles fonctionnent toutes.

Ce n'est pas une panne : aucune machine ne s'est arrêtée, aucune donnée n'est perdue. Le groupe s'est simplement scindé en deux moitiés qui continuent chacune de travailler, sans savoir ce que fait l'autre.

Le mot sert aussi, dans d'autres chapitres, à désigner un morceau de données : la part qu'une règle de répartition confie à une machine, au chapitre sur la répartition du stockage, ou la part d'une table rangée à part, que le chapitre sur l'interrogation apprend à choisir. Ici, une partition est toujours une coupure du réseau.

Une partition ne se distingue pas d'une lenteur. Une machine qui ne répond pas peut être arrêtée, saturée, ou séparée par le réseau. De l'extérieur, les trois cas sont identiques : il ne se passe rien.

Le système doit pourtant décider, après un délai qu'il fixe lui-même, si l'autre est morte ou seulement injoignable. Attendre plus longtemps améliore la justesse de la décision et dégrade le temps de réponse pour tout le monde.

C'est pourquoi une partition n'est pas un événement rare et exceptionnel : à l'échelle d'un cluster, un délai d'attente dépassé est une partition, et cela arrive tous les jours.

Vérification rapideon peut se reprendre

Qu'est-ce qu'une partition réseau ?

Le théorème CAP, énoncé correctement

Théorème CAP

Dans un système réparti, en présence d'une partition réseau, il faut choisir entre :

la cohérence, en refusant de répondre du côté qui n'est pas sûr d'être à jour,

la disponibilité, en répondant quand même, au risque de rendre une donnée périmée.

La tolérance aux partitions n'est pas un troisième choix : elle est subie. Un réseau finit toujours par se couper.

« Choisir deux propriétés sur trois » est une formulation fausse

La formule est commode et trompeuse, pour deux raisons.

D'abord, P ne se choisit pas. Renoncer à la tolérance aux partitions reviendrait à affirmer que le réseau ne se coupera jamais, ce qui n'est vrai d'aucun réseau. Un système réparti est donc toujours P, et le choix se réduit à deux options, pas à trois.

Ensuite, le choix ne s'applique que pendant la partition. Hors partition, un système peut parfaitement être cohérent et disponible en même temps, et c'est ce qu'il fait 99,9 % du temps. Décrire une base comme « AP » ne dit donc rien de son comportement ordinaire, seulement de ce qu'elle fait pendant les quelques secondes où le réseau se coupe.

L'extension qui décrit ce qui se passe le reste du temps

Un raffinement du théorème, appelé PACELC, complète l'énoncé : si une partition survient (P), choisir entre disponibilité (A) et cohérence (C) ; sinon (E, pour else), choisir entre latence (L) et cohérence (C).

La seconde moitié est celle qui compte au quotidien. Hors partition, garantir que toutes les copies répondent la même chose exige d'attendre qu'elles se soient parlé, donc d'ajouter de la latence à chaque opération. Le vrai arbitrage n'est pas « cohérence ou disponibilité » mais cohérence ou temps de réponse, et il se pose à chaque requête.

Vérification rapideon peut se reprendre

1.Pourquoi « choisir deux propriétés sur trois » est-il une formulation fautive du théorème CAP ?

2.Le C d'ACID et le C de CAP désignent…

BASE, et la cohérence à terme

Les propriétés BASE

Basically Available : le système répond, y compris de façon dégradée, plutôt que de refuser.

Soft state : l'état peut changer sans écriture, simplement parce que les copies se synchronisent en arrière-plan.

Eventually consistent : en l'absence de nouvelle écriture, toutes les copies finissent par converger vers la même valeur.

L'acronyme est un jeu de mots, acide contre base, et il ne faut pas y voir un modèle rigoureux. Il désigne une famille de compromis, dont le plus important est la cohérence à terme.

« Finissent par converger » ne dit rien du délai

La cohérence à terme garantit la convergence, pas sa rapidité. En pratique le délai se compte en millisecondes ; pendant une partition, il se compte en minutes, et rien dans la définition ne l'interdit.

Elle ne garantit pas non plus l'ordre dans lequel les lectures voient les valeurs. Sans précaution, un utilisateur peut lire une valeur récente, puis la valeur précédente, parce que ses deux lectures sont tombées sur des copies différentes. C'est déroutant, et c'est conforme.

Des garanties intermédiaires existent. Elles portent sur ce que voit un même client, et suffisent souvent là où la cohérence à terme déroute sans nuire :

lire ses propres écritures, pour que celui qui vient de modifier voie sa modification ;

lectures monotones, pour ne jamais reculer dans le temps ;

écritures ordonnées, pour que deux modifications successives s'appliquent dans l'ordre.

Elles ne règlent rien entre deux clients : deux personnes qui réservent le même siège ont besoin de la cohérence forte, et de son prix.

Vérification rapideon peut se reprendre

Que garantit exactement la cohérence à terme ?

Les quorums, ou comment acheter la cohérence

La cohérence n'est pas un interrupteur mais un réglage, et ce réglage se calcule. Une donnée est écrite sur N copies ; une écriture est confirmée quand W copies ont répondu ; une lecture interroge R copies et retient la plus récente.

R + W > N garantit de lire la dernière écriture. Si le nombre de copies lues plus le nombre de copies écrites dépasse le nombre total de copies, alors les deux ensembles se recoupent forcément : la lecture touche au moins une copie à jour, et la reconnaît à son horodatage.

Sous cette condition, la garantie tient, à trois réserves près. Les W et les R copies doivent être prises parmi les N copies désignées de la donnée : certains systèmes, pour rester disponibles, écrivent sur une autre machine quand une copie manque, et l'intersection n'est plus assurée. La version la plus récente doit se reconnaître sans dépendre d'horloges décalées. Et la garantie porte sur une lecture, pas sur un « lire puis écrire » que deux clients feraient en même temps. En dessous de la condition, aucune configuration ne rattrape la garantie.

Vérification rapideon peut se reprendre

Cinq copies, écriture confirmée par trois, lecture sur deux. La lecture rend-elle forcément la dernière écriture ?

La figure suivante écrit une version nouvelle sur W copies, puis lit R copies choisies dans le pire cas : les moins à jour parmi celles qui répondent. Une machine se coupe et se rétablit d'un clic ; vue du client, une machine arrêtée, saturée ou séparée par le réseau ne se distinguent pas, d'où le mot « injoignable ».

N = 5 copies

Un clic sur une machine la rend injoignable (arrêtée, saturée ou coupée par le réseau : vu du client, c'est pareil), un second la rétablit avec la version qu'elle avait.

Écrire une version nouvelle, puis lire. La lecture interroge les machines les moins à jour parmi celles qui répondent : c'est le cas qu'une garantie doit couvrir.

Lecture périmée possible

W + R = 4 ne dépasse pas N = 5 : 2 machines écrites et 2 machines lues peuvent ne pas se toucher.

L'écriture tolère 3 machines injoignables, la lecture 3.

Le solde d'un compte sur cinq copies. Écrire, puis lire dans le pire cas ; couper des machines, et voir ce que devient le réglage.
À manipuler
Avec W = 2 et R = 2, écrire puis lire : la version 2 n'est que sur les machines 1 et 2, la lecture interroge les machines 3 et 4 et rend la version 1. Trois des dix façons de choisir deux machines à lire manquent l'écriture.
Passer W et R à 3, écrire puis lire : la version 3 est sur les machines 1, 2 et 3, la lecture des machines 1, 4 et 5 la trouve, et aucune des dix façons de lire trois machines ne la manque.
Rendre injoignables les machines 3, 4 et 5, puis écrire : l'écriture est refusée, deux machines répondent et W en demande trois.
Abaisser W à 2 et écrire : la version 4 passe, sur les machines 1 et 2, mais W + R ne vaut plus que 5. Rétablir les trois machines et lire : la lecture rend la version 3, périmée. Rester disponible pendant la coupure a coûté la garantie : c'est le choix que pose le théorème CAP.
main.py
Sortie
>_ Prêt à exécuter…

Trois réglages méritent un nom, parce qu'ils correspondent à des choix courants.

RéglageR + WCe qu'on obtientCe qu'on paie
W = 1, R = 12écriture et lecture très rapides, disponibles tant qu'une copie répondaucune garantie de fraîcheur
W = 2, R = 24dernière écriture garantie, tolère une panne des deux côtéslatence de deux réponses à chaque opération
W = 3, R = 14dernière écriture garantie, lecture minimalel'écriture échoue dès qu'une copie est injoignable
Le réglage se choisit par opération, pas par base

Rien n'oblige à retenir le même compromis partout. Dans une même application, l'enregistrement d'un paiement demande W = 3, l'incrément d'un compteur de vues se contente de W = 1, et l'affichage d'un catalogue tolère parfaitement une lecture périmée de quelques secondes.

La question à poser n'est donc jamais « cette base est-elle cohérente ? » mais « que coûte, pour cette opération précise, de lire une valeur vieille de deux secondes ? ». Sur un solde bancaire, cela coûte cher. Sur un nombre de vues, cela ne coûte rien.

Quand deux copies divergent

Un système qui accepte des écritures des deux côtés d'une partition se retrouve, à la réconciliation, avec deux versions d'une même donnée. Il faut trancher, et trois stratégies existent.

Trois façons de réconcilier, de la plus simple à la plus juste. La dernière écriture gagne. On compare les horodatages et on garde le plus récent. Simple, et destructeur par construction : de deux écritures concurrentes, une seule survit, même avec des horloges parfaites. Des horloges décalées, ce qui est toujours le cas, ajoutent un second défaut : la version gardée n'est pas forcément la plus récente. Dans les deux cas, une écriture est perdue silencieusement.

Le conflit est signalé. Le système conserve les deux versions et les rend toutes les deux à la lecture suivante, à charge pour l'application de choisir. Honnête, et exigeant.

La structure absorbe le conflit. Certaines structures de données sont conçues pour fusionner sans ambiguïté : un compteur où chaque copie retient ses propres incréments, un ensemble où l'on ne fait qu'ajouter, ou un ensemble où un élément retiré ne revient jamais. La fusion devient alors un calcul, et non une décision.

Le rapprochement avec le chapitre sur le découpage du calcul est direct, à une exigence près. Une donnée qui se fusionne sans arbitrage a une opération de fusion associative et commutative, comme une réduction qui se recolle : dans les deux cas, il s'agit de recombiner des résultats partiels sans savoir dans quel ordre ils sont arrivés. Entre copies, la fusion doit aussi être idempotente : deux copies échangent leur état encore et encore, la même fusion est rejouée, et la rejouer ne doit rien changer. C'est pourquoi un compteur se fusionne en prenant, copie par copie, le plus grand des deux nombres d'incréments connus, et non en les additionnant.

Vérification rapideon peut se reprendre

Deux copies ont incrémenté un compteur pendant une partition. Quelle stratégie de réconciliation conserve tous les incréments ?

Mettre en pratique

Un quorum est un réglage à deux nombres, et une seule inégalité décide de ce qu'il garantit. Elle se vérifie en une soustraction.

Vérifier un réglage de quorum

  • 1.

    Avec 3 réplicas, un quorum d'écriture de 2 et un quorum de lecture de 2, combien vaut la somme du quorum d'écriture et du quorum de lecture ?

  • 2.

    Avec 5 réplicas et un quorum d'écriture de 2, quel est le plus petit quorum de lecture qui garantit de lire la dernière écriture ?

  • 3.

    Avec 5 réplicas et un quorum d'écriture de 3, combien de pannes simultanées l'écriture tolère-t-elle encore ?

  • 4.

    Avec 5 réplicas, quel réglage symétrique, c'est-à-dire avec le même quorum en lecture et en écriture, est le plus petit qui garantisse la cohérence ?

L'inégalité, et ce qu'elle achète. La garantie de lire la dernière écriture repose sur W+R>NW + R > N, quorums pris parmi les N réplicas désignés. Elle assure que l'ensemble des réplicas écrits et l'ensemble des réplicas lus ont au moins un élément commun, donc qu'au moins un répondant connaît la dernière valeur.
Le réglage se paie des deux côtés. Augmenter WW ralentit l'écriture et réduit le nombre de pannes tolérées en écriture ; augmenter RR ralentit la lecture. Un système à lectures fréquentes choisit donc un RR petit et un WW grand, et l'inverse pour un système à écritures fréquentes.

Un système est décrit comme « CP ». Que fait-il quand le réseau se coupe, et que fait-il le reste du temps ?

Pendant la partition, il privilégie la cohérence : le côté qui n'est pas sûr d'être à jour refuse de répondre, et renvoie une erreur plutôt qu'une donnée périmée. Une partie des clients est donc sans service pendant la coupure.

Le reste du temps, l'étiquette ne dit rien. Un système CP peut être rapide ou lent hors partition, selon qu'il attend ou non la confirmation de toutes les copies avant de répondre. C'est le second arbitrage de PACELC, et c'est celui qui décide de la latence perçue au quotidien.

Décrire un système par deux lettres est donc insuffisant : il faut connaître les deux arbitrages, pas un seul.

Cinq copies, écriture confirmée par trois, lecture sur deux. La dernière écriture est-elle garantie ?

R + W vaut 5, N vaut 5. La condition demande R + W strictement supérieur à N, donc 5 > 5 est faux : la garantie n'est pas acquise.

L'intuition le confirme. Les trois copies écrites et les deux copies lues peuvent être disjointes : il existe des ensembles de trois et de deux copies parmi cinq qui ne se recoupent pas. La lecture peut alors ne voir que des copies périmées.

Passer la lecture à trois copies donne R + W = 6 > 5 et rétablit la garantie, au prix d'une réponse de plus à attendre.

Un compteur de vues est incrémenté sur deux copies pendant une partition, de 100 à 105 d'un côté et de 100 à 103 de l'autre. Que doit valoir le compteur après réconciliation, et que donne la stratégie de la dernière écriture ?

La bonne réponse est 108 : cinq vues d'un côté, trois de l'autre, huit en tout.

La stratégie de la dernière écriture donne 105 ou 103 selon les horloges, et perd donc entre trois et cinq incréments sans rien signaler.

Le remède est structurel et non procédural. Un compteur qui retient, par copie, le nombre d'incréments qu'elle a vus se fusionne en prenant, pour chaque copie, le plus grand des deux nombres connus, et sa valeur est 100 plus la somme de ces nombres : (5, 3), soit 108. Le résultat ne dépend ni de l'ordre ni des horloges, et rejouer la fusion ne change rien, là où une addition rejouée compterait deux fois les trois vues du second côté : l'opération est associative, commutative et idempotente.

Dans une application de réservation de places, quel compromis retenir pour la consultation du nombre de places restantes, et pour la réservation elle-même ?

Deux opérations, deux compromis, dans la même application.

La consultation tolère une valeur périmée de quelques secondes : afficher « 12 places » alors qu'il en reste 11 n'a aucune conséquence. Lecture sur une copie, réponse immédiate, disponibilité maximale.

La réservation ne tolère rien : deux clients ne doivent pas obtenir la même place. Un quorum ne suffit pas : R + W > N garantit qu'une lecture voit la dernière écriture terminée, pas que deux clients ne lisent pas « libre » au même moment avant d'écrire chacun leur nom. Avec trois copies et R = W = 2, le client A peut lire les copies 1 et 2, le client B les copies 2 et 3, tous deux trouver le siège libre, puis écrire chacun sur deux copies et recevoir chacun sa confirmation. Il faut une écriture conditionnelle, « attribuer le siège 12 s'il est encore libre », décidée par un protocole de consensus entre les copies, comme les transactions dites légères de certaines bases réparties. Du côté minoritaire d'une partition, ce protocole ne peut pas conclure : c'est le choix de la cohérence, refuser le service plutôt que vendre deux fois le même siège.

C'est le cas général : une application n'a pas un compromis, elle en a un par opération, et les mélanger revient soit à payer une cohérence inutile, soit à vendre deux fois la même place.

Chapitre révisé en octobre 2026 · Une erreur dans ce chapitre ?

Dans la bibliothèque d'exercices