Marcio Cunha

Consistência Transacional em Microsserviços com Saga por Orquestração

Descubra como manter dados sincronizados entre múltiplos bancos independentes usando o padrão Saga baseado em orquestração e compensação assíncrona, superando os limites das transações tradicionais.

Marcio Cunha•5 min
Também disponível em:EnglishEspañol
Resumo
  • Transações ACID tradicionais tornam-se inviáveis em arquiteturas de microsserviços devido ao acoplamento estrito entre bancos de dados heterogêneos.
  • O padrão Saga substitui bloqueios globais por uma sequência de transações locais coordinateas de forma assíncrona.
  • A abordagem baseada em orquestração centraliza a lógica de fluxo, facilitando auditorias e o rastreamento de falhas.
  • A compensação assíncrona desfaz ações passadas por meio de eventos reversos quando um erro ocorre no meio do processo.
  • Mensagerias robustas garantem a entrega confiável de mensagens, viabilizando a consistência eventual em larga escala.

O Desafio da Consistência em Sistemas Distribuídos

Quando separamos um sistema monolítico gigante em vários microsserviços menores, ganhamos independência de deploy e escalabilidade, mas perdemos um recurso muito útil dos bancos de dados tradicionais: as transações atômicas, conhecidas pela sigla ACID, que garantem que tudo seja salvo ou nada seja alterado. Em um cenário distribuído, cada microsserviço possui seu próprio banco de dados isolado e independente, o que significa que não podemos usar comandos simples para travar tabelas em servidores diferentes e garantir que uma compra seja finalizada apenas se o estoque e o pagamento funcionarem juntos perfeitamente. Na prática, isso significa que precisamos lidar com falhas parciais onde o pagamento é debitado com sucesso, mas o serviço de envio falha ao registrar o frete, criando um estado inconsistente que exige intervenção manual se não for tratado automaticamente pela aplicação.

O Padrão Saga como Alternativa ao Bloqueio Global

Para resolver esse dilema sem sacrificar a escalabilidade dos microsserviços, a engenharia de software adota o padrão Saga, que consiste em uma sequência de transações locais coordenadas de forma distribuída. Cada serviço envolvido executa sua própria operação transacional de forma independente e emite um evento informando se o processo teve sucesso ou se falhou. Se todas as etapas da cadeia forem concluídas sem problemas, o fluxo chega ao fim com sucesso e o estado global atinge a consistência esperada de forma gradual, conceito conhecido como consistência eventual. Na prática, em vez de manter uma linha de produção inteiramente travada aguardando o operador mais lento, permitimos que cada etapa trabalhe no seu ritmo, aceitando que o sistema passe por breves instantes de divergência antes de se alinhar completamente.

Orquestração versus Coreografia no Controle de Fluxo

Existem duas maneiras principais de implementar o padrão Saga: por coreografia e por orquestração, sendo a segunda a escolha mais segura para fluxos complexos de negócios. Na coreografia, cada microsserviço escuta eventos e decide o que fazer sozinho, como um músico tocando de ouvido em uma banda sem maestro, o que funciona bem em cenários simples mas vira uma bagunça difícil de rastrear conforme o sistema cresce. Na orquestração, por sua vez, existe um componente centralizador dedicado — o orquestrador — que conhece todo o fluxo de ponta a ponta e diz explicitamente a cada serviço qual é o próximo passo a ser executado. Na prática, isso significa que o desenvolvedor ganha uma visão unificada do processo de negócio em um único lugar, facilitando drasticamente a depuração de erros e a adição de novas regras sem precisar alterar dezenas de microsserviços diferentes.

Para ilustrar como um orquestrador gerencia esse processo, podemos analisar um trecho de código em Python usando uma abordagem assíncrona para despachar comandos e aguardar respostas:

import asyncio

async def executar_saga_pedido(pedido_id):
    print(f"Iniciando Saga para o pedido {pedido_id}")
    pagamento_ok = await chamar_servico_pagamento(pedido_id)
    if not pagamento_ok:
        await compensar_pagamento(pedido_id)
        return "Falha no pagamento"
    
    estoque_ok = await chamar_servico_estoque(pedido_id)
    if not estoque_ok:
        await compensar_pagamento(pedido_id)
        return "Falha no estoque, pagamento estornado"
    
    return "Pedido concluído com sucesso"

O Mecanismo de Compensação Assíncrona

Como não podemos simplesmente dar um comando de desfazer (rollback) em bancos de dados separados e geograficamente distantes, a Saga utiliza a compensação assíncrona para reverter efeitos colaterais quando algo dá errado. Se o pagamento foi aprovado, mas o estoque esgotou logo em seguida, o orquestrador não desfaz o passado apagando registros magicamente, ele emite uma nova ordem de negócio que executa o inverso da ação original, como um estorno do cartão de crédito. Na prática, a transação compensatória é uma operação normal de negócio projetada especificamente para anular o impacto da anterior, exigindo planejamento prévio e cuidado redobrado com regras fiscais e restrições de tempo limite. Essa abordagem garante que o sistema mantenha a integridade funcional mesmo operando em ambientes altamente descentralizados, tolerando quedas temporárias de rede sem corromper os dados dos usuários.

Garantindo Resiliência com Filas de Mensagens

A comunicação entre o orquestrador e os microsserviços nunca deve ser feita por chamadas síncronas diretas do tipo HTTP, pois a queda momentânea de um único nó derrubaria o fluxo inteiro de ponta a ponta. Em vez disso, utilizamos brokers de mensagens assíncronas como RabbitMQ, Apache Kafka ou AWS SQS para enfileirar as ordens de processamento e garantir que nenhuma mensagem seja perdida caso um serviço fique fora do ar por alguns minutos. Na prática, isso significa que se o serviço de nota fiscal estiver reiniciando para uma atualização, a mensagem de emissão aguardará pacientemente na fila até que o servidor volte a ficar operacional, retomando o processamento exatamente do ponto onde parou. Essa resiliência estrutural protege a integridade financeira e operacional da empresa, transformando falhas inevitáveis de infraestrutura em meros atrasos temporários na esteira de processamento.

Considerações Finais sobre Arquiteturas Orientadas a Eventos

Adotar o padrão Saga baseado em orquestração e compensação assíncrona exige uma mudança profunda no modelo mental dos desenvolvedores, que precisam abandonar a ilusão de que transações instantâneas e globais são sempre possíveis. Embora a consistência eventual traga complexidade adicional no tratamento de estados intermediários e na concepção de transações compensatórias, os ganhos em escalabilidade, resiliência e independência arquitetural compensam amplamente o esforço. Na prática, sistemas modernos de grande porte só conseguem crescer de forma sustentável quando aceitam que a coordenação assíncrona e tolerante a falhas é o único caminho viável para unir serviços heterogêneos. Planejar cuidadosamente o comportamento do orquestrador e testar cenários de falha injetando instabilidade de rede são passos fundamentais para construir aplicações robustas e preparadas para o mundo real.