Поделиться через


Реплицированные зерна

Иногда может быть несколько экземпляров одного и того же активного зерна, например при работе с несколькими кластерами и использовании OneInstancePerClusterAttribute. ЖурналedGrain предназначен для поддержки реплика экземпляров с минимальными трениями. Он зависит от поставщиков согласованности журналов для выполнения необходимых протоколов, чтобы убедиться, что все экземпляры согласуются с одной последовательностью событий. В частности, он заботится о следующих аспектах:

  • Согласованные версии: все версии состояния зерна (за исключением предварительных версий) основаны на одной глобальной последовательности событий. В частности, если два экземпляра видят одинаковый номер версии, то они видят одно и то же состояние.

  • Гоночные события: несколько экземпляров могут одновременно вызывать событие. Поставщик согласованности разрешает эту гонку и гарантирует, что все согласны с одной последовательностью.

  • Уведомления и реактивность. После того, как событие возникает в одном экземпляре, поставщик согласованности не только обновляет хранилище, но и уведомляет всех остальных экземпляров зерна.

Общие сведения о согласованности см. в документе TechReport и GSP (глобальный протокол последовательности).

Условные события

Гоночные события могут быть проблематичными, если у них конфликт, т. е. не должны оба фиксации по какой-то причине. Например, при выводе денег с банковского счета два экземпляра могут независимо определить, есть ли достаточные средства для вывода и выдача события вывода. Но сочетание обоих событий может перезарыть. Чтобы избежать этого, JournaledGrain API поддерживает RaiseConditionalEvent метод.

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

Условные события дважды проверка, если локальная версия соответствует версии в хранилище. Если нет, это означает, что последовательность событий выросла в то же время, что означает, что это событие потеряло гонку против другого события. В этом случае условное событие не добавляется в журнал и RaiseConditionalEvent возвращает значение false.

Это аналог использования электронных тегов с обновлениями условного хранилища, а также простой механизм для предотвращения фиксации конфликтующих событий.

Можно и разумно использовать как условные, так и безусловные события для одного и того же зерна, например a DepositEvent и a WithdrawalEvent. Депозиты не должны быть условными: даже если DepositEvent раса теряет гонку, ее не нужно отменить, но все равно можно добавить к глобальной последовательности событий.

Ожидание возвращаемой RaiseConditionalEvent задачи достаточно для подтверждения события, т. е. не требуется также вызывать ConfirmEvents.

Явная синхронизация

Иногда желательно убедиться, что зерно полностью догон до последней версии. Это можно применить путем вызова:

await RefreshNow();

Он выполняет две задачи.

  1. Он подтверждает все неподтвержденные события.
  2. Она загружает последнюю версию из хранилища.