Dans le domaine de la conception de systèmes distribués, l'une des décisions les plus critiques qu'un architecte doit prendre concerne la gestion de la cohérence des données. Alors que nous passons de bases de données à nœud unique à des clusters distribués, les garanties relatives à la visibilité des données changent fondamentalement. Bien que le théorème CAP stipule de manière célèbre qu'un système distribué ne peut garantir que deux propriétés sur trois (Cohérence, Disponibilité et Tolérance aux partitions), la réalité du développement d'applications modernes nécessite une compréhension nuancée des différents modèles de cohérence.
Le spectre de la cohérence
La cohérence n'est pas un interrupteur binaire ; c'est un spectre allant de la linéarisabilité stricte à la cohérence finale relâchée. Comprendre ces modèles permet aux développeurs d'adapter le comportement de leur système à des cas d'utilisation spécifiques, en équilibrant performance, coût et expérience utilisateur.
Cohérence forte
La cohérence forte (ou linéarisabilité) garantit que toute opération de lecture renvoie l'écriture la plus récente. Dans un système à cohérence forte, si un client met à jour une valeur, toutes les lectures ultérieures à travers l'ensemble du système refléteront cette mise à jour immédiatement. Ce modèle est crucial pour les transactions financières, la gestion des stocks et les systèmes d'authentification, où la précision des données est primordiale.
Cependant, la cohérence forte a souvent un coût élevé en termes de latence et de disponibilité lors des partitions de réseau, car les nœuds doivent se coordonner pour convenir de l'état des données avant de répondre.
Cohérence finale
La cohérence finale est une garantie plus faible. Elle promet qu'avec suffisamment de temps et sans autres mises à jour, toutes les répliques convergeront vers le même état. Pendant la fenêtre de convergence, différents nœuds peuvent renvoyer des valeurs différentes pour la même clé. Ce modèle est populaire dans les systèmes distribués à l'échelle mondiale comme le DNS, les flux des réseaux sociaux et les couches de mise en cache, où la haute disponibilité et la faible latence sont prioritaires par rapport à la précision immédiate.
// Exemple : Code pseudo démontrant le comportement de cohérence finale
class ReplicatedDatabase {
constructor(replicas) {
this.replicas = replicas;
}
write(key, value) {
// Écriture sur la réplique locale immédiatement
this.replicas[0].put(key, value);
// Réplication asynchrone vers les autres nœuds
this.replicas.slice(1).forEach(replica => {
setTimeout(() => replica.put(key, value), Math.random() * 1000);
});
}
read(key) {
// Peut renvoyer des données périmées de la réplique 2 ou 3
// jusqu'à ce que la réplication asynchrone soit terminée
return this.replicas[Math.floor(Math.random() * 3)].get(key);
}
}
Modèles de cohérence intermédiaires
Entre les extrêmes de la cohérence forte et de la cohérence finale se trouvent plusieurs modèles intermédiaires qui offrent différents compromis :
- Lire ses propres écritures : Garantit que si un client écrit des données, les lectures ultérieures par le même client verront ces données, même si d'autres clients ne les ont pas encore vues.
- Cohérence de session : Étend le principe de « Lire ses propres écritures » pour inclure les lectures monotones (une fois que vous avez vu une valeur, vous ne voyez jamais une version plus ancienne) et les écritures monotones (les écritures concurrentes sont sérialisées par client).
- Cohérence causale : Garantit que les opérations liées de manière causale sont vues dans le même ordre par tous les clients. Par exemple, si l'utilisateur A voit un message, puis que l'utilisateur B y commente, l'utilisateur A devrait éventuellement voir le commentaire.
Choisir le bon modèle
Le choix d'un modèle de cohérence n'est pas une solution unique pour tous. Il nécessite une compréhension approfondie des exigences de l'application. Pour une application bancaire, la cohérence forte est non négociable. Pour un réseau de diffusion de contenu (CDN) servant des images statiques, la cohérence finale est parfaitement acceptable et souvent préférée pour des raisons de performance.
Les bases de données distribuées modernes comme Amazon DynamoDB, Cassandra et CockroachDB permettent aux développeurs de régler les niveaux de cohérence sur une base par requête. Cette flexibilité permet aux architectes de construire des systèmes qui sont à la fois hautement disponibles et suffisamment cohérents pour chaque chemin de logique métier spécifique.
Conclusion
Maîtriser les modèles de cohérence est essentiel pour construire des systèmes distribués résilients et évolutifs. En dépassant la pensée binaire « cohérent vs incohérent », les développeurs peuvent concevoir des systèmes offrant le bon équilibre entre performance et intégrité des données. Que vous choisissiez la cohérence forte pour des opérations financières critiques ou la cohérence finale pour des fonctionnalités sociales à grande échelle, comprendre les compromis sous-jacents est la clé d'une architecture système réussie.