Transações distribuídas do Saga

Azure

O padrão de design saga é uma maneira de gerenciar a consistência de dados entre microsserviços em cenários de transação distribuída. Uma saga é uma sequência de transações que atualiza cada serviço e publica uma mensagem ou evento para disparar a próxima etapa de transação. Se uma etapa falhar, a saga executará transações compensatórias que contrariam as transações anteriores.

Contexto e problema

Uma transação é uma única unidade de lógica ou trabalho, às vezes composta por várias operações. Em uma transação, um evento é uma alteração de estado que ocorre em uma entidade e um comando encapsula todas as informações necessárias para executar uma ação ou disparar um evento posterior.

As transações devem ser ACID (atômicas, consistentes, isoladas e duráveis). As transações em um único serviço são ACID, mas a consistência de dados entre serviços requer uma estratégia de gerenciamento de transações entre serviços.

Em arquiteturas de vários serviços:

  • Atomicidade é um conjunto indivisível e irredutível de operações que devem ocorrer ou nenhuma que deve ocorrer.
  • Consistência significa que a transação traz os dados somente de um estado válido para outro estado válido.
  • O isolamento garante que transações simultâneas produzam o mesmo estado de dados que transações executadas sequencialmente teriam produzido.
  • A durabilidade garante que as transações confirmadas permaneçam confirmadas mesmo em caso de falha no sistema ou interrupção de energia.

Um modelo de banco de dados por microsserviço oferece muitos benefícios para arquiteturas de microsserviços. Encapsular dados de domínio permite que cada serviço use seu melhor tipo de armazenamento de dados e esquema, dimensione seu próprio armazenamento de dados conforme necessário e seja isolado das falhas de outros serviços. No entanto, garantir a consistência de dados entre bancos de dados específicos do serviço tem alguns desafios.

Transações distribuídas como o protocolo 2PC (confirmação de duas fases) exigem que todos os participantes de uma transação confirmem ou revertam antes que a transação possa prosseguir. No entanto, algumas implementações de participantes, como bancos de dados NoSQL e agente de mensagens, não dão suporte a esse modelo.

Outra limitação de transação distribuída é a sincronização e a disponibilidade da comunicação entre processos (IPC). A IPC fornecida pelo sistema operacional permite que processos separados compartilhem dados. Para que transações distribuídas sejam confirmadas, todos os serviços participantes devem estar disponíveis, potencialmente reduzindo a disponibilidade geral do sistema. Implementações arquitetônicas com IPC ou limitações de transação são candidatas ao padrão Saga.

Solução

O padrão Saga fornece gerenciamento de transações usando uma sequência de transações locais. Uma transação local é o esforço de trabalho atômico realizado por um participante da saga. Cada transação local atualiza o banco de dados e publica uma mensagem ou evento para disparar a próxima transação local na saga. Se uma transação local falhar, a saga executará uma série de transações compensatórias que desfazem as alterações feitas pelas transações locais anteriores.

Saga overview.

Padrão dentro do Saga:

  • Transações compensáveis são transações que podem ser potencialmente revertidas processando outra transação com o efeito oposto.
  • Uma transação dinâmica é o ponto ir/não-ir em uma saga. Se a transação dinâmica for confirmada, a saga será executada até a conclusão. Uma transação dinâmica pode ser uma transação que não é compensada nem com nova tentativa, ou pode ser a última transação compensável ou a primeira transação com nova tentativa na saga.
  • Transações com nova tentativa são transações que seguem a transação dinâmica e têm a garantia de sucesso.

Há duas abordagens comuns de implementação de saga, coreografia e orquestração. Cada abordagem tem seu próprio conjunto de desafios e tecnologias para coordenar o fluxo de trabalho.

Coreografia

A coreografia é uma maneira de coordenar sagas em que os participantes trocam eventos sem um ponto centralizado de controle. Com a coreografia, cada transação local publica eventos de domínio que disparam transações locais em outros serviços.

Choreography Overview

Benefícios

  • Bom para fluxos de trabalho simples que exigem poucos participantes e não precisam de uma lógica de coordenação.
  • Não requer implementação e manutenção de serviço adicionais.
  • Não introduz um único ponto de falha, pois as responsabilidades são distribuídas entre os participantes da saga.

Desvantagens

  • O fluxo de trabalho pode se tornar confuso ao adicionar novas etapas, pois é difícil rastrear quais participantes da saga escutam quais comandos.
  • Há um risco de dependência cíclica entre os participantes da saga porque eles têm que consumir os comandos uns dos outros.
  • O teste de integração é difícil porque todos os serviços devem estar em execução para simular uma transação.

Orquestração

A orquestração é uma maneira de coordenar sagas em que um controlador centralizado informa aos participantes da saga quais transações locais executar. O orquestrador de saga manipula todas as transações e informa aos participantes qual operação executar com base em eventos. O orquestrador executa solicitações de saga, armazena e interpreta os estados de cada tarefa e lida com a recuperação de falhas com a compensação de transações.

Orchestration Overview

Benefícios

  • Bom para fluxos de trabalho complexos envolvendo muitos participantes ou novos participantes adicionados ao longo do tempo.
  • Adequado quando há controle sobre cada participante no processo e controle sobre o fluxo de atividades.
  • Não introduz dependências cíclicas, pois o orquestrador depende unilateralmente dos participantes da saga.
  • Os participantes da saga não precisam saber sobre comandos para outros participantes. A separação clara de preocupações simplifica a lógica de negócios.

Desvantagens

  • A complexidade de design externa requer uma implementação de uma lógica de coordenação.
  • Há um ponto de falha externo, pois o orquestrador gerencia o fluxo de trabalho completo.

Problemas e considerações

Considere os seguintes pontos ao implementar o padrão Saga:

  • O padrão saga pode inicialmente ser desafiador, pois requer uma nova maneira de pensar em como coordenar uma transação e manter a consistência de dados para um processo empresarial que abrange vários microsserviços.
  • O padrão Saga é particularmente difícil de depurar, e a complexidade cresce à medida que os participantes aumentam.
  • Os dados não podem ser revertidos porque os participantes da saga confirmam alterações em seus bancos de dados locais.
  • A implementação deve ser capaz de lidar com um conjunto de possíveis falhas transitórias e fornecer idempotência para reduzir efeitos colaterais e garantir a consistência dos dados. A Idempotência significa que a mesma operação pode ser repetida várias vezes sem alterar o resultado inicial. Para obter mais informações, consulte as diretrizes sobre como garantir a idempotência ao processar mensagens e atualizar o estado juntos.
  • É melhor implementar a observabilidade para monitorar e acompanhar o fluxo de trabalho da saga.
  • A falta de isolamento de dados do participante impõe desafios de durabilidade. A implementação da saga deve incluir contramedidas para reduzir anomalias.

As seguintes anomalias podem ocorrer sem as medidas adequadas:

  • Atualizações perdidas, quando uma saga grava sem ler as alterações feitas por outra saga.
  • Leituras sujas, quando uma transação ou uma saga lê atualizações feitas por uma saga que ainda não concluiu essas atualizações.
  • Leituras difusas/não repetíveis, quando diferentes etapas da saga leem dados diferentes porque ocorre uma atualização de dados entre as leituras.

As contramedidas sugeridas para reduzir ou evitar anomalias incluem:

  • Bloqueio semântico, um bloqueio no nível do aplicativo em que a transação compensada de uma saga usa um semáforo para indicar que uma atualização está em andamento.
  • Atualizações comutativas que podem ser executadas em qualquer ordem e produzem o mesmo resultado.
  • Exibição pessimista: É possível que uma saga leia dados sujos, enquanto outra saga está executando uma transação compensável para reverter a operação. A exibição pessimista reordena a saga para que os dados subjacentes sejam atualizados em uma transação com nova tentativa, o que elimina a possibilidade de uma leitura suja.
  • O valor de releitura verifica se os dados estão inalterados e, em seguida, atualiza o registro. Se o registro tiver sido alterado, as etapas serão abortadas e a saga poderá ser reiniciada.
  • Um arquivo de versão registra as operações em um registro quando elas chegam e as executa na ordem correta.
  • Por valor, usa o risco comercial de cada solicitação para selecionar dinamicamente o mecanismo de simultaneidade. Solicitações de baixo risco favorecem sagas, enquanto solicitações de alto risco favorecem transações distribuídas.

Quando usar esse padrão

Use o padrão saga quando precisar:

  • Verificar a consistência de dados em um sistema distribuído sem estreitamento ligado.
  • Reverter ou compensar se uma das operações na sequência falhar.

O padrão saga é menos adequado para:

  • Transações com estreitamento ligado.
  • Compensar transações que ocorrem em participantes anteriores.
  • Dependências cíclicas.

Exemplo

A Saga baseada em orquestração Sem Servidor é uma referência de implementação de saga usando a abordagem de orquestração que simula um cenário de transferência de dinheiro com fluxos de trabalho bem-sucedidos e com falha.

Próximas etapas

  • Dados distribuídos
  • Richardson, Chris. 2018: Padrões de microsserviços. Manning Publications.

Os seguintes padrões também serão úteis ao implementar este padrão:

  • A coreografia faz com que cada componente do sistema participe do processo de tomada de decisão sobre o fluxo de trabalho de uma transação de negócios, em vez de depender de um ponto central de controle.
  • Compensar transações desfaz o trabalho executado por uma série de etapas e, eventualmente, define uma operação consistente se uma ou mais etapas falharem. Aplicativos hospedados na nuvem que implementam processos de negócios complexos e fluxos de trabalho geralmente seguem esse modelo de consistência eventual.
  • Repetir permite que um aplicativo trate falhas transitórias quando tentar se conectar a um serviço ou recurso de rede ao repetir de forma transparente uma operação com falha. Repetir pode melhorar a estabilidade do aplicativo.
  • O disjuntor trata as falhas que podem consumir uma quantidade variável de tempo para serem recuperadas ao se conectar a um serviço ou recurso remoto. O disjuntor pode melhorar a estabilidade e a resiliência de um aplicativo.
  • Monitoramento de integridade do ponto de extremidade Implemente verificações funcionais dentro de um aplicativo cujas ferramentas externas podem acessar por meio de pontos de extremidade expostos em intervalos regulares. O monitoramento de integridade do ponto de extremidade pode ajudar a verificar se os aplicativos e serviços estão funcionando corretamente.