Compartilhar via


Grãos replicados

Às vezes, pode haver várias instâncias do mesmo grão ativo, como ao operar um multicluster e usar o OneInstancePerClusterAttribute. O JournaledGrain foi projetado para oferecer suporte a instâncias replicadas com o mínimo de atrito. Ele depende de provedores de consistência de log para executar os protocolos necessários para garantir que todas as instâncias concordem com a mesma sequência de eventos. Em particular, ele cuida dos seguintes aspectos:

  • Versões consistentes: Todas as versões do estado granular (exceto as versões provisórias) são baseadas na mesma sequência global de eventos. Em particular, se duas instâncias virem o mesmo número de versão, elas verão o mesmo estado.

  • Eventos de corrida: várias instâncias podem gerar um evento simultaneamente. O provedor de consistência resolve essa disputa e garante que todos concordem com a mesma sequência.

  • Notificações/Reatividade : depois que um evento é gerado em uma instância de grão único, o provedor de consistência não apenas atualiza o armazenamento, mas também notifica todas as outras instâncias de grão.

Para uma discussão geral sobre a consistência, consulte nosso TechReport e o documento GSP (Protocolo de Sequência Global).

Eventos condicionais

Eventos de corrida podem ser problemáticos se tiverem um conflito, ou seja, ambos não devem se comprometer por algum motivo. Por exemplo, ao retirar dinheiro de uma conta bancária, duas instâncias podem determinar independentemente que há fundos suficientes para uma retirada e emitir um evento de retirada. Mas a combinação de ambos os eventos poderia ultrapassar. Para evitar isso, a API dá suporte a JournaledGrain um RaiseConditionalEvent método.

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

Os eventos condicionais verificam novamente se a versão local corresponde à versão no armazenamento. Caso contrário, significa que a sequência de eventos cresceu nesse meio tempo, o que significa que este evento perdeu uma corrida contra algum outro evento. Nesse caso, o evento condicional não é anexado ao log e RaiseConditionalEvent retorna falso.

Isso é análogo ao uso de e-tags com atualizações de armazenamento condicional e também fornece um mecanismo simples para evitar a confirmação de eventos conflitantes.

É possível e sensato usar eventos condicionais e incondicional para o mesmo grão, como um DepositEvent e um WithdrawalEvent. Os depósitos não precisam ser condicionais: mesmo que uma DepositEvent corrida perca, ela não precisa ser cancelada, mas ainda pode ser acrescentada à sequência de eventos global.

Aguardar a tarefa retornada por RaiseConditionalEvent é suficiente para confirmar o evento, ou seja, não é necessário chamar também ConfirmEvents.

Sincronização explícita

Às vezes, é desejável garantir que um grão esteja totalmente envolvido com a versão mais recente. Isso pode ser imposto chamando:

await RefreshNow();

Isso faz duas coisas:

  1. Confirma todos os eventos não confirmados.
  2. Ele carrega a versão mais recente do armazenamento.