Modèle de cohérence
Clustron Zaris vous offre une vue cohérente et prévisible de vos données à travers les nœuds. Cet article explique ce que cela signifie en pratique, afin que vous puissiez prévoir le comportement des lectures et des écritures — et savoir quand vous devez ajouter de la coordination par-dessus.
Ce que la cohérence signifie ici
La cohérence concerne la façon dont les données se comportent lorsque plusieurs choses se produisent en même temps : plusieurs nœuds détiennent les données, plusieurs clients lisent et écrivent la même clé, et des mises à jour arrivent de manière concurrente. Le modèle est conçu pour équilibrer trois objectifs — exactitude, disponibilité et performance — de sorte qu'il ne poursuit pas des garanties absolues au prix de son utilisabilité.
Un seul store logique
Même en mode distribué, un store se présente comme un store logique unique. Vous adressez le store, pas les nœuds individuels, et vous ne gérez pas vous-même la réplication ni le routage des requêtes vers des nœuds spécifiques. De nombreux nœuds soutiennent le store, mais vous raisonnez sur une seule vue cohérente :
Plusieurs nœuds → une seule vue cohérente
C'est le fondement sur lequel tout le reste repose : le code de votre application traite un store distribué de la même manière qu'un store en processus.
Comment se comportent les lectures et les écritures
Les écritures sont appliquées à travers le cluster, qui maintient le store dans un état cohérent à mesure que les changements arrivent. Vous ne coordonnez pas la réplication entre les nœuds — c'est la responsabilité du système.
Les lectures renvoient la dernière valeur connue. De façon cruciale, une fois qu'une écriture réussit, les lectures ultérieures reflètent cette écriture. Ce comportement de lecture-après-écriture (read-after-write) est ce qui vous permet d'écrire une valeur puis de compter sur sa relecture, plutôt que de douter de la propagation de la mise à jour.
La lecture-après-écriture tient parce que les lectures vont vers le primaire par défaut, et le primaire est l'endroit où les écritures arrivent. Si vous activez les lectures sur réplica (AllowReplicaReads) sous la réplication Async par défaut, une lecture servie par un réplica en retard peut renvoyer des données périmées — la lecture-après-écriture n'est alors plus garantie. Consultez Partitionnement et réplication pour les détails de routage et de mode de réplication.
Pour la plupart des applications, le résultat est que vous interagissez avec le store comme s'il s'agissait d'une instance unique : des lectures et des écritures prévisibles, aucune réplication manuelle, et aucune comptabilité de cohérence à travers les nœuds.
Configurer la cohérence
Les réglages qui façonnent ces garanties se trouvent dans la configuration du store. Les valeurs par défaut (réplication Async, lectures sur le primaire uniquement) vous donnent la lecture-après-écriture d'emblée ; modifiez-les lorsqu'une charge de travail exige des compromis différents :
- Mode de réplication —
replication.mode:Async(par défaut ; latence la plus basse, un basculement peut perdre les écritures les plus récentes) ouSync(attend les réplicas, durabilité plus forte). AvecSync,replication.quorum(All,MajorityouBestEffort) décide combien de réplicas doivent accuser réception. - Lectures sur réplica —
reads.allowReplicaReads(par défautfalse). Ne l'activez que pour les charges de travail à forte lecture qui tolèrent des lectures légèrement périmées ; cela échange la lecture-après-écriture contre du débit de lecture.
{
"replication": { "factor": 2, "mode": "Sync", "quorum": "Majority" },
"reads": { "allowReplicaReads": false }
}
Le facteur de réplication est défini lorsque vous créez le store (New-ZrStore -ReplicationFactor). Pour chaque champ et valeur par défaut, consultez la référence de configuration.
Mises à jour concurrentes de la même clé
Lorsque plusieurs clients mettent à jour la même clé en même temps, le store traite les opérations de manière sûre et converge vers un résultat cohérent — vous ne vous retrouverez pas avec une valeur corrompue ou à moitié écrite. Ce qu'une écriture simple ne fait pas, c'est vérifier si quelqu'un d'autre a modifié la clé avant.
Un simple PutAsync est une écriture aveugle : il écrase ce qui se trouve là, de sorte que deux clients mettant à jour la même clé de manière concurrente peuvent produire une mise à jour perdue — la deuxième écriture remplace silencieusement la première. Si l'exactitude d'une mise à jour dépend de la valeur que vous avez lue, ne comptez pas sur les écritures ordinaires. Utilisez une transaction, qui détecte un changement conflictuel et échoue au lieu d'écraser, ou un verrou ou un bail pour garantir qu'un seul client met à jour la clé à la fois.
Le même modèle dans les deux modes
Le modèle de cohérence est identique en mode en processus et en mode distribué. Votre application n'a pas besoin d'une logique différente selon l'endroit où le store s'exécute, ce qui rend sûr de développer contre un store en processus et de déployer contre un store distribué.
Quand vous avez besoin de garanties plus fortes
Le comportement par défaut suffit pour des lectures et des écritures simples. Lorsqu'une opération a besoin d'ordre, d'exclusivité ou de sémantique tout-ou-rien, tournez-vous vers les primitives de coordination :
- Les verrous pour donner à un client un accès exclusif et empêcher les mises à jour conflictuelles.
- Les transactions pour regrouper plusieurs opérations afin qu'elles s'appliquent ensemble, avec détection de conflit via la concurrence optimiste.
- Les baux pour gérer la propriété d'une ressource et la libérer automatiquement en cas de panne.
Cela vous permet d'opter pour une coordination plus forte exactement là où vous en avez besoin, sans la payer à chaque opération.