Compartilhar via


Padrão de transação de compensação

Use este modelo para desfazer o trabalho quando uma ou mais etapas falharem em uma operação eventualmente consistente. Aplicativos hospedados na nuvem que implementam processos de negócios complexos e fluxos de trabalho geralmente usam operações que seguem o modelo de consistência eventual.

Contexto e problema

Aplicativos de nuvem frequentemente modificam dados que são espalhados por várias fontes de dados em diferentes localizações geográficas. Para evitar contenção e melhorar o desempenho em um ambiente distribuído, os aplicativos devem implementar uma consistência eventual em vez de uma consistência transacional forte. No modelo de consistência eventual, uma operação de negócios típica consiste em uma série de etapas separadas. Durante essas etapas, a exibição geral do estado do sistema pode ser inconsistente. Mas o sistema deve se tornar consistente novamente quando todas as etapas forem concluídas.

Lidar com falhas de etapa apresenta um desafio fundamental no modelo de consistência eventual. Após uma falha, pode ser necessário desfazer o trabalho realizado em etapas de operação concluídas. No entanto, nem sempre é possível reverter os dados porque outras instâncias de aplicativo simultâneas podem alterar os dados. Mesmo quando instâncias simultâneas não alteram os dados, pode ser mais complexo desfazer uma etapa do que restaurar o estado original. Talvez seja necessário aplicar regras específicas aos negócios. Para obter um exemplo, consulte o exemplo do site de viagens.

Quando uma operação que implementa a consistência eventual abrange vários armazenamentos de dados, você deve acessar cada armazenamento de dados para desfazer as alterações. Para impedir que o sistema permaneça inconsistente, você deve desfazer de maneira confiável o trabalho em cada repositório de dados.

Uma operação que implementa a consistência eventual nem sempre armazena seus dados afetados em um banco de dados. Por exemplo, em um ambiente SOA (arquitetura orientada a serviço), uma operação pode invocar uma ação em um serviço e alterar o estado que o serviço mantém. Para desfazer a operação, você também deve desfazer essa alteração de estado, que pode envolver invocar o serviço novamente para reverter os efeitos da primeira ação.

Solução

Implemente uma transação compensante que desfaça os efeitos das etapas concluídas na operação original. Você pode pensar que pode simplesmente restaurar o sistema para seu estado original, mas essa abordagem pode substituir alterações de outras instâncias de aplicativo simultâneas. Em vez disso, a transação compensadora deve considerar de forma inteligente o trabalho simultâneo. Esse processo geralmente é específico do aplicativo e depende da operação original.

Você pode usar um fluxo de trabalho para implementar uma operação eventualmente consistente que requer compensação. À medida que a operação original é executada, o sistema registra informações sobre cada etapa e como desfazê-la. Se a operação falhar, o fluxo de trabalho retrocederá pelas etapas concluídas e reverterá cada etapa.

Diagrama que mostra as etapas para criar um itinerário e as etapas da transação de compensação que cancelam o itinerário.

Embora cada etapa seja uma ação separada, juntas, elas formam uma operação eventualmente consistente. O sistema deve executar as etapas e as operações de desfazer correspondentes para cada etapa. Se o cliente cancelar, essas operações de desfazer poderão ser executadas como uma transação compensatória.

Uma falha em uma única etapa nem sempre exige que você restabeleça todo o sistema usando uma transação de compensação. Por exemplo, em um cenário de site de viagens, um cliente registra os voos F1, F2 e F3, mas não consegue reservar um quarto no hotel H1. Oferecer ao cliente um quarto em um hotel diferente é preferível a cancelar os voos. O cliente ainda pode optar por cancelar, o que dispara a transação de compensação para desfazer as reservas de voo. No entanto, o cliente deve tomar essa decisão, não o sistema. Quando as decisões são de alto impacto ou difíceis de automatizar de forma confiável, inclua um humano no processo de tomada de decisão.

Considere estes pontos importantes:

  • Uma transação compensante pode não precisar desfazer o trabalho na ordem inversa exata da operação original.

  • Você pode executar algumas etapas de desfazer em paralelo.

  • Talvez seja necessário aplicar regras específicas aos negócios. Por exemplo, o cancelamento de uma reserva de voo pode não dar ao cliente o direito a um reembolso total.

Essa abordagem é semelhante ao padrão de transações distribuídas da Saga.

As transações de compensação são operações eventualmente consistentes e podem falhar. O sistema deve registrar o progresso para que possa retomar a transação de compensação do ponto de falha. Uma etapa pode ser executada várias vezes quando repetida, portanto, projete cada etapa como um comando idempotente.

Às vezes, a intervenção manual é a única maneira de se recuperar de uma etapa com falha. Nessas situações, o sistema deve gerar um alerta que inclua informações detalhadas sobre o motivo da falha.

Problemas e considerações

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

  • Não é fácil determinar quando uma etapa em uma operação que implementa a consistência eventual falha. Uma etapa pode não falhar imediatamente, mas, em vez disso, ser bloqueada. Talvez seja necessário implementar um mecanismo de tempo limite.

  • Não é fácil generalizar a lógica da compensação. Uma transação de compensação é específica do aplicativo. Isso depende de o aplicativo ter informações suficientes para desfazer os efeitos de cada passo em uma operação com falha.

  • Transações compensatórias nem sempre funcionam. Defina as etapas em uma transação compensatória como comandos idempotentes para que você possa repeti-las se a transação compensante em si falhar.

  • A infraestrutura que trata das etapas deve atender aos seguintes critérios:

    • Ele é resiliente tanto na operação original quanto na transação de compensação.

    • Ele não perde as informações necessárias para compensar uma etapa com falha.

    • Ele monitora de forma confiável o progresso da lógica de compensação. Transações de compensação são executadas após a confirmação das operações originais, e outras transações podem alterar os estados intermediários. Portanto, verifique se você pode correlacionar e auditar a operação original e sua compensação de ponta a ponta.

  • Uma transação de compensação não retorna necessariamente os dados do sistema ao seu estado no início da operação original. Em vez disso, a transação compensa o trabalho que a operação concluiu com êxito antes de ter falhado.

  • As etapas de transação de compensação nem sempre revertem a operação original na ordem exatamente oposta. Por exemplo, se um armazenamento de dados for mais sensível a inconsistências do que outro, desfaça as alterações nesse repositório primeiro.

  • Algumas medidas podem ajudá-lo a melhorar as taxas de sucesso. Você pode colocar um bloqueio de curto prazo com um tempo limite em cada recurso necessário para concluir uma operação. Você pode adquirir esses recursos com antecedência e executar o trabalho somente depois de adquirir todos os recursos. Finalize todas as ações antes dos bloqueios expirarem.

  • A lógica de repetição que trata mais erros como transitórios pode ajudar a minimizar falhas que disparam uma transação de compensação. Quando uma etapa em uma operação que implementa a consistência eventual falhar, considere-a como uma exceção transitória e tente novamente a etapa. Só interrompa a operação e dispare a compensação se a etapa falhar repetidamente ou você não conseguir recuperá-la. Para obter mais informações sobre estratégias de repetição, consulte Tratamento transitório de falhas.

  • Ao implementar uma transação compensadora, você enfrenta muitos desafios semelhantes à implementação de consistência eventual. Para obter mais informações, consulte Minimizar a coordenação.

  • Defina pontos claros sem retorno e etapas irreversíveis. Em fluxos de trabalho complexos, você não pode desfazer algumas operações com segurança ou de forma significativa, como efeitos colaterais externos ou ações legalmente vinculativas. Identificar etapas compensaveis versus irreversíveis. Projete o fluxo de trabalho para que as etapas irreversíveis ocorram somente depois que todas as validações críticas forem bem-sucedidas.

Quando usar esse padrão

Use esse padrão quando:

  • Uma operação de negócios abrange várias etapas, serviços ou armazenamentos de dados e deve ser desfeita se uma etapa posterior falhar. Esse cenário geralmente ocorre em fluxos de trabalho de execução longa que seguem um modelo de consistência eventual e não podem depender de transações atômicas.

  • A recuperação de falha geralmente requer lógica específica do domínio em vez de uma simples reversão de dados. Usar ações de compensação ao desfazer o trabalho exige que você aplique regras de negócios, como cancelar reservas ou emitir reembolsos parciais.

O padrão pode não ser adequado nestes casos:

  • As operações podem ser repetidas com segurança e a maioria das falhas é transitória. Somente a lógica de repetição geralmente é suficiente nesses casos e transações de compensação acrescentam complexidade desnecessária.

  • O sistema não pode tolerar inconsistência temporária ou a compensação não pode restaurar de forma confiável um estado válido. Use mecanismos de consistência fortes ou transações atômicas em todas as etapas.

Design de carga de trabalho

Avalie como usar a Transação Compensante no design de uma carga de trabalho para atingir as metas e princípios definidos nos pilares do Azure Well-Architected Framework. A tabela a seguir fornece diretrizes sobre como esse padrão dá suporte às metas de cada pilar.

Pilar Como esse padrão apoia os objetivos do pilar
As decisões de design de confiabilidade ajudam sua carga de trabalho a se tornar resiliente ao mau funcionamento e garantir que ela se recupere para um estado totalmente funcional após a ocorrência de uma falha. As ações de compensação resolvem falhas em caminhos de carga de trabalho críticos usando processos como reverter diretamente as alterações de dados, quebrar bloqueios de transação ou até mesmo executar o comportamento do sistema nativo para reverter o efeito.

- RE:02 Fluxos críticos
- RE:09 Recuperação de desastre

Se esse padrão introduzir compensações dentro de um pilar, considere-as em relação aos objetivos dos outros pilares.

Exemplo

O diagrama a seguir mostra uma implementação prática de Azure do padrão de Transação de Compensação. Outras implementações também podem funcionar para seus requisitos de carga de trabalho. Um orquestrador executado em Azure Container Apps coordena cada etapa de um fluxo de trabalho de execução longa enviando comandos por meio de Azure Service Bus. À medida que cada etapa adiante é bem-sucedida, o orquestrador registra o estado de execução e a ação de compensação correspondente em Azure Cosmos DB para que o fluxo de trabalho possa ser retomado, correlacionado e auditado.

Diagrama que mostra uma implementação Azure do padrão de transação compensante.

Esse modelo usa novas tentativas primeiro para preservar o progresso futuro. Se uma etapa falhar, o orquestrador aplicará a lógica de repetição para falhas transitórias e tentará continuar a operação original. A compensação é invocada somente quando o progresso futuro se torna impossível, como quando as novas tentativas são esgotadas ou a falha é classificada como não transisiente.

As regras específicas aos negócios também podem preferir o progresso futuro em vez da compensação imediata. Se uma etapa falhar, o orquestrador poderá selecionar um caminho alternativo, como substituir um serviço equivalente ou uma opção de fallback, em vez de reverter o fluxo de trabalho. Para casos de alto impacto ou ambíguos, você pode pausar o fluxo de trabalho para revisão humana antes de decidir se deseja continuar em um caminho alternativo ou disparar uma compensação. Essa abordagem trata a compensação como último recurso e permite que as regras de domínio conduzam as decisões de recuperação.

Em uma sequência típica, o orquestrador envia mensagens de etapas através do Service Bus (etapas 1 e 2), recebe resultados bem-sucedidos e armazena metadados de encaminhamento e compensação no Azure Cosmos DB.

Você pode disparar a compensação de duas maneiras:

  • Quando uma etapa subsequente na mesma carga de trabalho falha e você deve desfazer etapas anteriormente concluídas com êxito. Essa compensação pode ocorrer imediatamente quando uma etapa retorna um erro de negócios, como uma falha de validação de regra ou depois que as novas tentativas técnicas são esgotadas e a mensagem é movida para a fila de mensagens mortas.

  • Quando um cliente subsequente solicita explicitamente cancelar uma operação concluída.

Em ambos os casos, o orquestrador lê os registros de compensação armazenados e envia comandos de compensação para o serviço correspondente. Se uma etapa de compensação falhar transitóriamente, Service Bus novas tentativas poderão concluí-la sem escalar o incidente.

Se novas tentativas repetidas ainda falharem, Service Bus moverá a mensagem para uma fila de mensagens mortas e preservará os detalhes da falha. O orquestrador, ou um processador de mensagens mortas dedicado, gera um alerta e emite telemetria estruturada, incluindo o motivo da falha e as IDs de correlação, para Azure Monitor e Log Analytics, que podem aparecer no Application Insights. Esse caminho operacional ajuda as equipes a diagnosticar falhas, determinar a necessidade de intervenção manual e manter a rastreabilidade nos fluxos originais e compensatórios.

O fluxo de trabalho pode iniciar a compensação automaticamente por condições claras e de baixo risco ou pausar para revisão humana quando a situação for ambígua, de alto impacto ou exigir uma decisão manual.

Use identidades gerenciadas e autorização baseada em Microsoft Entra ID entre componentes para evitar segredos compartilhados e impor acesso de privilégios mínimos. Ao criar um diagrama de referência simplificado, trate esses controles de identidade e autorização como questões de implementação de linha de base em vez de etapas de fluxo explícitas. Mantenha o diagrama focado na orquestração, repetição, compensação e tratamento de falhas.

  • Considerações de dados para microsserviços: saiba por que a consistência eventual e a falha parcial são inerentes a sistemas distribuídos. O padrão Compensating Transaction fornece um mecanismo concreto para lidar com essas falhas quando as operações abrangem vários serviços.

  • Transactional Outbox pattern com Azure Cosmos DB: use esse padrão quando transações de compensação precisam publicar eventos ou comandos de forma confiável. Ele ajuda a garantir que as alterações de estado e as mensagens sejam registradas atomicamente, o que impede a perda de mensagens.

  • Design para autorrecuperação: Use transações compensatórias como parte de uma abordagem de autorrecuperação para seus aplicativos.

  • Padrão Supervisor do Agente de Agendamento: use esse padrão para implementar sistemas resilientes que realizam operações de negócios em serviços e recursos distribuídos. Esses sistemas às vezes precisam de transações compensatórias para reverter o trabalho.

  • Padrão de repetição: use esse padrão para lidar com falhas transitórias e minimizar a necessidade de compensação de transações.

  • Padrão de transações distribuídas da Saga: use esse padrão para gerenciar a consistência de dados entre microsserviços em transações distribuídas. A Saga usa transações de compensação para recuperação de falhas.

  • Padrão de Pipes e Filtros: Use esse padrão com o Padrão de Transação Compensatória como uma alternativa às transações distribuídas ao decompor tarefas complexas em etapas reutilizáveis.