Padrão de transações distribuídas da Saga

Azure

Mantenha a consistência de dados em sistemas distribuídos coordenando uma sequência de transações locais em vários serviços. Cada serviço executa sua operação e dispara a próxima etapa por meio de eventos ou mensagens. Se uma etapa falhar, uma série de transações compensatórias desfazerá as alterações feitas pelas etapas concluídas.

Contexto e problema

Uma transação representa uma unidade de trabalho, que pode incluir várias operações. Em uma transação, um evento refere-se a uma alteração de estado que afeta uma entidade. Um comando encapsula todas as informações necessárias para executar uma ação ou disparar um evento subsequente.

As transações devem seguir os princípios de atomicidade, consistência, isolamento e durabilidade (ACID).

  • Atomicidade: Todas as operações têm êxito ou nenhuma operação tem êxito.
  • Consistência: transições de dados de um estado válido para outro estado válido.
  • Isolamento: As transações concorrentes produzem os mesmos resultados que as transações sequenciais.
  • Durabilidade: as alterações persistem após serem confirmadas, mesmo quando ocorrem falhas.

Em um único serviço, as transações seguem os princípios ACID porque operam em um único banco de dados. No entanto, pode ser mais complexo alcançar a conformidade com ACID em vários serviços.

Desafios em arquiteturas de microsserviços

As arquiteturas de microsserviços normalmente atribuem um banco de dados dedicado a cada microsserviço. Essa abordagem oferece vários benefícios:

  • Cada serviço encapsula seus próprios dados.
  • Cada serviço pode usar a tecnologia de banco de dados e o esquema mais adequados para suas necessidades específicas.
  • Os bancos de dados para cada serviço podem ser dimensionados de forma independente.
  • Falhas em um serviço são isoladas de outros serviços.

Apesar dessas vantagens, essa arquitetura complica a consistência de dados entre serviços. Garantias de banco de dados tradicionais, como ACID, não são diretamente aplicáveis a vários armazenamentos de dados gerenciados independentemente. Devido a essas limitações, as arquiteturas que dependem da comunicação entre processos ou modelos de transação tradicionais, como o protocolo de confirmação de duas fases, geralmente são mais adequadas para o padrão saga.

Solução

O padrão Saga gerencia transações dividindo-as em uma sequência de transações locais .

Diagrama que mostra uma visão geral da saga.

Cada transação local:

  1. Executa seu trabalho atomicamente em um único serviço.
  2. Atualiza o banco de dados do serviço.
  3. Inicia a próxima transação por meio de um evento ou mensagem.

Se uma transação local falhar, a saga executará uma série de transações de compensação para reverter as alterações feitas pelas transações locais anteriores.

Principais conceitos no padrão saga

  • transações compensadas podem ser desfeitas ou compensadas por outras transações com o efeito oposto. Se uma etapa da saga falhar, as transações de compensação desfazem as alterações que as transações compensáveis realizaram.

  • transações dinâmicas servem como ponto sem retorno na saga. Depois que uma transação pivot for concluída com êxito, as transações compensáveis deixarão de ser relevantes. Todas as ações subsequentes devem ser concluídas para que o sistema alcance um estado final consistente. Uma transação pivot pode assumir diferentes papéis, dependendo do fluxo da saga:

    • Transações irreversíveis ou não compensáveis não podem ser desfeitas nem tentadas novamente.

    • O limite entre reversível e efetivada significa que a transação pivô pode ser a última transação desfazível ou compensável. Ou pode ser a primeira operação passível de nova tentativa na saga.

  • Transações repetíveis seguem a transação pivô. As transações passíveis de repetição são idempotentes e ajudam a garantir que a saga possa atingir seu estado final, mesmo que ocorram falhas temporárias. Eles ajudam a saga a eventualmente alcançar um estado consistente.

Abordagens de implementação de saga

As duas abordagens típicas de implementação da saga são de coreografia e de orquestração. Cada abordagem tem seu próprio conjunto de desafios e tecnologias para coordenar o fluxo de trabalho.

Coreografia

Na abordagem coreográfica, os serviços trocam eventos sem um controlador centralizado. Com a coreografia, cada transação local publica eventos de domínio que acionam transações locais em outros serviços.

Diagrama que mostra uma saga usando a coreografia.

Benefícios da coreografia Desvantagens da coreografia
Bom para fluxos de trabalho simples que têm poucos serviços e não precisam de uma lógica de coordenação. O fluxo de trabalho pode ser confuso quando você adiciona novas etapas. É difícil rastrear a quais comandos cada participante da saga responde.
Nenhum outro serviço é necessário para coordenação. Há um risco de dependência cíclica entre os participantes da saga porque eles têm que consumir os comandos uns dos outros.
Não introduz um único ponto de falha porque as responsabilidades são distribuídas entre os participantes da saga. O teste de integração é difícil porque todos os serviços devem ser executados para simular uma transação.

Orquestração

Na orquestração, um controlador centralizado ou orquestrador, manipula todas as transações e informa aos participantes qual operação executar com base em eventos. O orquestrador executa as requisições de saga, armazena e interpreta os estados de cada tarefa e gerencia a recuperação de falhas por meio de transações compensatórias.

Diagrama que mostra uma saga usando orquestração.

Benefícios da orquestração Desvantagens da orquestração
Mais adequado para fluxos de trabalho complexos ou quando você adiciona novos serviços. Outra complexidade de design requer uma implementação de uma lógica de coordenação.
Evita dependências cíclicas porque o orquestrador gerencia o fluxo. Apresenta um ponto de falha porque o orquestrador gerencia o fluxo de trabalho completo.
A separação clara de responsabilidades simplifica a lógica do serviço.

Problemas e considerações

Considere os seguintes pontos ao decidir como implementar esse padrão:

  • Mudança na forma de pensar sobre design: Adotar o padrão Saga exige uma mentalidade diferente. Isso exige que você se concentre na coordenação de transações e na consistência de dados em vários microsserviços.

  • Complexidade das sagas de depuração: sagas de depuração podem ser complexas, especificamente à medida que o número de serviços participantes aumenta.

  • alterações irreversíveis do banco de dados local: Dados não podem ser revertidos porque os participantes da saga confirmam alterações em seus respectivos bancos de dados.

  • Tratamento de falhas transitórias e idempotência: O sistema deve lidar com falhas transitórias de forma eficaz e garantir que a idempotência, ao repetir a mesma operação, não altere o resultado. Para obter mais informações, consulte processamento idempotente de mensagens.

  • Necessidade de monitorar e acompanhar sagas: Monitoramento e acompanhamento do fluxo de trabalho de uma saga são tarefas essenciais para manter a supervisão operacional.

  • Limitações de compensação de transações: as transações de compensação podem nem sempre ter êxito, o que pode deixar o sistema em um estado inconsistente.

Possíveis anomalias de dados em sagas

Anomalias de dados são inconsistências que podem ocorrer quando as sagas operam em vários serviços. Como cada serviço gerencia seus próprios dados, chamados dados de participantes, não há isolamento interno entre os serviços. Essa configuração pode resultar em inconsistências de dados ou problemas de durabilidade, como atualizações parcialmente aplicadas ou conflitos entre serviços. Problemas típicos incluem:

  • Atualizações perdidas: quando uma saga modifica dados sem considerar as alterações feitas por outra saga, isso resulta em atualizações substituídas ou ausentes.

  • Leituras sujas: Quando uma saga ou transação lê dados que outra saga modificou, mas a modificação ainda não foi concluída.

  • Leituras difusas, ou não repetíveis: Quando diferentes etapas em uma saga leem dados inconsistentes porque as atualizações ocorrem entre as leituras.

Estratégias para lidar com anomalias de dados

Para reduzir ou evitar essas anomalias, considere as seguintes contramedidas:

  • Bloqueio semântico: Use bloqueios em nível de aplicação quando a transação compensável de uma saga usa um semáforo para indicar que uma atualização está em andamento.

  • atualizações comutativas: atualizações de design para que possam ser aplicadas em qualquer ordem enquanto ainda produzem o mesmo resultado. Essa abordagem ajuda a reduzir conflitos entre sagas.

  • Visão pessimista: Reordenar a sequência da saga de modo que as atualizações de dados ocorram em transações passíveis de repetição para eliminar leituras sujas. Caso contrário, uma saga pode ler dados sujos, ou alterações não confirmadas, enquanto outra saga executa simultaneamente uma transação compensável para reverter suas atualizações.

  • Valores relidos: Confirme que os dados permanecem inalterados antes de fazer atualizações. Se os dados forem alterados, interrompa a etapa atual e reinicie a saga conforme necessário.

  • Arquivos de versão: Manter um log de todas as operações executadas em um registro e garantir que elas sejam executadas na sequência correta para evitar conflitos.

  • simultaneidade baseada em risco com base no valor: escolha dinamicamente o mecanismo de simultaneidade apropriado com base no risco de negócios potencial. Por exemplo, use sagas para atualizações de baixo risco e transações distribuídas para atualizações de alto risco.

Quando usar esse padrão

Use esse padrão quando:

  • Você precisa garantir a consistência de dados em um sistema distribuído sem acoplamento apertado.
  • Você precisa reverter ou compensar se uma das operações na sequência falhar.

Esse padrão pode não ser adequado quando:

  • As transações são firmemente acopladas.
  • As transações compensatórias ocorrem nos participantes anteriores.
  • Há dependências cíclicas.

Próxima etapa

Os seguintes padrões podem ser relevantes quando você implementa esse padrão:

  • O padrão coreográfico tem cada componente do sistema participando do processo de tomada de decisão sobre o fluxo de trabalho de uma transação comercial, em vez de depender de um ponto central de controle.

  • O padrão compensação de 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.

  • O padrão de repetição permite que um aplicativo trate falhas transitórias quando tenta se conectar a um serviço ou recurso de rede repetindo de forma transparente a operação com falha. Esse padrão pode melhorar a estabilidade do aplicativo.

  • O padrão Circuit Breaker lida com falhas que demoram um tempo variável para serem recuperadas, quando você se conecta a um serviço ou recurso remoto. Esse padrão pode melhorar a estabilidade e a resiliência de um aplicativo.

  • O padrão de monitoramento de endpoints de integridade implementa verificações funcionais em uma aplicação, que podem ser acessadas por ferramentas externas por meio de endpoints expostos em intervalos regulares. Esse padrão pode ajudá-lo a verificar se os aplicativos e serviços estão sendo executados corretamente.