Software · Soluções na Prática

Transações Distribuídas e Padrão Saga: Consistência sem 2PC em Microsserviços

Como equipes de engenharia orquestram fluxos transacionais entre microsserviços através de Sagas, transações compensatórias e consistência eventual.

Diagrama de padrão Saga orquestrado e coreografado ilustrando transações locais e transações compensatórias em microsserviços

No desenvolvimento de sistemas monolíticos tradicionais apoiados em um único banco de dados relacional, garantir a atomicidade de uma operação de negócio complexa é uma tarefa trivial: o desenvolvedor abre uma transação local (BEGIN TRANSACTION), executa as atualizações nas tabelas de pedidos, estoque e faturamento e, caso qualquer regra falhe, emite um ROLLBACK. O próprio motor do banco de dados encarrega-se de desfazer todas as alterações instantaneamente, garantindo que o sistema nunca permaneça em um estado inconsistente.

No entanto, quando a organização adota a arquitetura de microsserviços com o princípio fundamental de Banco de Dados por Serviço (Database-per-Service), essa facilidade desaparece: o serviço de pedidos possui seu próprio banco de dados, o serviço de pagamentos possui o seu e o serviço de logística opera sobre outro banco totalmente independente.

Tentar aplicar transações distribuídas clássicas de duas fases (Two-Phase Commit - 2PC) nesse ambiente distribuído na nuvem é um erro fatal de arquitetura, gerando bloqueios de linha prolongados, dependência de coordenadores únicos e indisponibilidade sistêmica.

Para solucionar esse desafio sem abrir mão da confiabilidade transacional, arquiteturas distribuídas utilizam o Padrão Saga e transações compensatórias.

Por Que o Two-Phase Commit (2PC) Não Funciona na Nuvem

O protocolo 2PC foi concebido para redes locais de computadores nas décadas de 1980 e 1990. Ele opera em duas etapas estritamente síncronas:

  1. Fase de Preparação: Um coordenador central pergunta a todos os bancos participantes se eles estão prontos para o commit. Cada banco adquire travas exclusivas nas linhas e aguarda.
  2. Fase de Confirmação: Se todos responderem afirmativamente, o coordenador emite a ordem final de gravação.

Na computação em nuvem moderna, o 2PC colapsa devido a três fatores fundamentais:

  • Amplificação de Latência: Uma transação fica bloqueada pelo tempo que a rede mais lenta entre os bancos demorar para responder.
  • Ponto Único de Falha no Coordenador: Se o nó coordenador cair enquanto os bancos mantêm travas ativas, os dados ficam congelados e inacessíveis para novos usuários.
  • Violação do Teorema CAP: Em caso de partição temporária de rede entre data centers, o 2PC sacrifica sumariamente a disponibilidade de todo o ecossistema.

A Anatomia do Padrão Saga

O Padrão Saga, formalizado originalmente por Hector Garcia-Molina em 1987, decompõe uma grande transação distribuída em uma sequência ordenada de transações locais independentes ($T_1, T_2, \dots, T_n$). Cada transação local atualiza o banco de dados de um único microsserviço e emite um evento ou comando assíncrono para disparar a próxima etapa da cadeia.

Se alguma etapa intermediária falhar (por exemplo, a tentativa de cobrança do cartão de crédito for recusada pelo banco ou o produto estiver esgotado no armazém), a Saga executa uma série de Transações Compensatórias ($C_1, C_2, \dots, C_{n-1}$) na ordem reversa, desfazendo semanticamente os efeitos das etapas anteriores:

flowchart LR
    subgraph Success["FLUXO DE SUCESSO"]
        direction LR
        S1["1. Cria pedido"] --> S2["2. Reserva crédito"] --> S3["3. Separa estoque"] --> S4["4. Conclui pedido"]
    end

    subgraph Failure["FALHA E COMPENSAÇÃO"]
        direction LR
        F1["1. Cria pedido"] --> F2["2. Reserva crédito"] --> F3["3. Estoque esgotado"] --> Comp["Inicia compensação"] --> Undo2["Estorna crédito"] --> Undo1["Cancela pedido"]
    end

    classDef success fill:#0f2724,stroke:#34d399,color:#f8fafc;
    classDef failure fill:#321c24,stroke:#f87171,color:#f8fafc;
    class S1,S2,S3,S4 success;
    class F1,F2,F3,Comp,Undo2,Undo1 failure;

O Que é uma Transação Compensatória?

Uma transação compensatória não é um "undo mágico" a nível de disco; trata-se de uma ação de negócio explícita que neutraliza semanticamente o estado anterior:

  • Se a transação inicial inseriu uma reserva temporária de crédito, a compensação emite um estorno no cartão.
  • Se a transação inicial reservou uma vaga em um voo, a compensação cancela o bilhete e libera o assento novamente para venda.

As Duas Formas de Coordenação de Saga

Existem duas abordagens arquiteturais para orquestrar a execução de uma Saga:

1. Coreografia (Choreography - Descentralizada)

Não há um maestro central. Cada microsserviço ouve eventos no message broker (Kafka ou RabbitMQ) e reage publicando novos eventos.

  • Vantagens: Simplicidade de implementação para fluxos curtos de 2 a 3 etapas, alto desacoplamento.
  • Desvantagens: Em fluxos com muitas etapas, a lógica fica espalhada por dezenas de repositórios, tornando difícil rastrear em qual estado a transação se encontra e entender o fluxo completo.

2. Orquestração (Orchestration - Centralizada com Máquina de Estados)

Um componente dedicado (o Orquestrador de Saga) atua como um maestro explícito, mantendo o estado da transação persistido e emitindo comandos diretos para cada microsserviço participante.

  • Vantagens: Visibilidade total do ciclo de vida, facilidade para gerenciar fluxos complexos de dezenas de passos, implementação transparente de timeouts e compensações estruturadas.
  • Desvantagens: Exige infraestrutura de máquina de estados confiável (como MassTransit Saga State Machine no .NET, Camunda ou Temporal).

Padrões Recomendados para Implementação de Sagas

Em microsserviços de missão crítica, a implementação do padrão Saga costuma seguir critérios rigorosos de resiliência:

  1. Orquestração com Máquinas de Estados Persistentes: Para processos centrais de negócio (checkout, faturamento e integração contábil), adotamos orquestração explícita. O estado da Saga é persistido em banco de dados relacional através de transações ACID locais com concorrência otimista, impedindo que a reinicialização de um servidor perca o andamento de transações em curso.
  2. Transactional Outbox Integrado: As mensagens de comando despachadas pelo orquestrador e os eventos de resposta dos microsserviços utilizam o Transactional Outbox Pattern. Garantimos matematicamente que nenhum evento seja perdido em oscilações de rede (At-Least-Once Delivery).
  3. Idempotência Absoluta em Todos os Consumidores: Como mensagens podem ser retransmitidas em cenários de retry automático de rede, cada método de execução e de compensação é estritamente idempotente, verificando identificadores únicos de transação (SagaCorrelationId) antes de aplicar qualquer alteração financeira.
  4. Trilhas de Auditoria e Telemetria End-to-End: Cada Saga gera um span raiz no OpenTelemetry que envelopa todas as etapas e transações compensatórias, permitindo que a equipe de operações visualize o progresso do fluxo em tempo real através de dashboards unificados.