Partager via


Grains répliqués

Parfois, plusieurs instances du même grain peuvent être actives, par exemple lors de l’exploitation d’un cluster multiple et à l’aide du OneInstancePerClusterAttribute. JournaledGrain est conçu pour prendre en charge les instances répliquées avec une friction minimale. Il s’appuie sur les fournisseurs de cohérence des journaux pour exécuter les protocoles nécessaires afin de s’assurer que toutes les instances conviennent de la même séquence d’événements. En particulier, il gère les aspects suivants :

  • Versions cohérentes : toutes les versions de l’état du grain (à l’exception des versions provisoires) sont basées sur la même séquence globale d’événements. En particulier, si deux instances voient le même numéro de version, elles voient le même état.

  • Événements de course : plusieurs instances peuvent déclencher simultanément un événement. Le fournisseur de cohérence résout cette course et garantit que toutes les instances sont d’accord sur la même séquence.

  • Notifications/réactivité : une fois qu’un événement est déclenché à une instance de grain, le fournisseur de cohérence met non seulement à jour le stockage, mais avertit également toutes les autres instances de grain.

Pour une discussion générale sur le modèle de cohérence, consultez notre document TechReport et le document GSP (Global Sequence Protocol).

Événements conditionnels

Les événements de course peuvent être problématiques s’ils entrent en conflit, c’est-à-dire que ni l'un ni l'autre ne devraient avoir lieu pour une raison quelconque. Par exemple, lors du retrait de l’argent d’un compte bancaire, deux instances peuvent déterminer indépendamment les fonds suffisants pour un retrait et émettre un événement de retrait. Toutefois, la combinaison des deux événements pourrait dépasser le compte. Pour éviter cela, l’API JournaledGrain prend en charge la RaiseConditionalEvent méthode.

bool success = await RaiseConditionalEvent(
    new WithdrawalEvent() { /* ... */ });

Les événements conditionnels vérifient deux fois si la version locale correspond à la version dans le stockage. Si ce n’est pas le cas, cela signifie que la séquence d’événements a augmenté entretemps, indiquant que cet événement a été devancé par un autre événement. Dans ce cas, l’événement conditionnel n’est pas ajouté au journal et RaiseConditionalEvent retourne false.

Cela est analogue à l’utilisation de balises électroniques avec des mises à jour de stockage conditionnel et fournit un mécanisme simple pour éviter la validation d’événements en conflit.

Il est possible et judicieux d’utiliser à la fois des événements conditionnels et inconditionnels pour le même grain, comme DepositEvent et WithdrawalEvent. Les dépôts n’ont pas besoin d’être conditionnels : même si une DepositEvent course perd, elle n’a pas besoin d’être annulée, mais peut toujours être ajoutée à la séquence d’événements globale.

Attendre la tâche retournée par RaiseConditionalEvent suffit pour confirmer l’événement ; vous n’avez pas besoin d’appeler ConfirmEvents.

Synchronisation explicite

Parfois, vous souhaiterez peut-être vous assurer qu’un grain est complètement à jour avec la dernière version. Vous pouvez appliquer cela en appelant :

await RefreshNow();

Cet appel effectue deux opérations :

  1. Confirme tous les événements non confirmés.
  2. Charge la dernière version à partir du stockage.