O Dilema da Consistência em Microsserviços: Transações Distribuídas vs. Saga vs. Eventual Consistency

Em um monólito, garantir consistência de dados é simples: use uma transação ACID no banco de dados. Se algo falha, tudo é desfeito. Em microsserviços, cada serviço tem seu próprio banco. O que acontece quando um pedido precisa reservar estoque, processar pagamento e agendar entrega – e uma dessas etapas falha?

Esse é o dilema da consistência em microsserviços. Não há bala de prata. Cada abordagem tem trade-offs entre consistência, disponibilidade e performance.

Neste post, vamos explorar as três principais estratégias: transações distribuídas (XA), padrão Saga (coreografado e orquestrado), e consistência eventual com eventos. Com exemplos práticos e orientações sobre quando usar cada uma.

O problema em uma imagem

No fluxo de criação de pedido, se o estoque reserva mas o pagamento falha, como desfazer a reserva? Em um monólito, uma transação resolve. Em microsserviços, você precisa coordenar serviços independentes.

1. Transações Distribuídas (XA / Two-Phase Commit)

Baseadas no padrão Two-Phase Commit (2PC). Um coordenador (transação global) pergunta a todos os participantes se estão prontos para commitar (fase 1) e depois ordena o commit (fase 2).

Vantagem: Consistência forte (ACID entre serviços).

Desvantagens:

  • Alto acoplamento (todos precisam responder rápido).
  • Bloqueio de recursos (locks podem travar o sistema).
  • Baixa disponibilidade: se o coordenador ou qualquer participante falha, a transação pode ficar pendente.
  • Pobre escalabilidade.

Exemplo de tecnologia: XA com Atomikos, Narayana, ou JTA em Java.

Quando usar: Raramente. Apenas em sistemas financeiros legados que exigem consistência imediata e têm baixa escala. Não recomendado para a maioria dos microsserviços modernos.

2. Padrão Saga

Saga divide a transação longa em uma sequência de transações locais. Cada etapa executa uma ação e publica um evento ou chama o próximo serviço. Se uma etapa falha, o saga executa transações compensatórias para desfazer as anteriores.

Tipos de Saga

Saga Coreografada (Choreographed)

Cada serviço publica eventos que disparam o próximo serviço. Não há coordenador central.

Vantagens: Baixo acoplamento, fácil evolução.

Desvantagens: Fluxo difícil de rastrear (eventos espalhados), risco de loops acidentais.

Saga Orquestrada (Orchestrated)

Um orquestrador central (um serviço Saga) comanda cada etapa e sabe como compensar.

Vantagens: Fluxo centralizado, fácil monitorar, compensações claras.

Desvantagens: Orquestrador pode tornar-se ponto único de acoplamento e de falha.

Exemplo prático: Saga orquestrada com pedidos

// Orquestrador simplificado
public class CreateOrderSaga {
    private final PedidoService pedidoService;
    private final EstoqueService estoqueService;
    private final PagamentoService pagamentoService;

    public void execute(CreateOrderCommand cmd) {
        // Etapa 1
        var pedidoId = pedidoService.criarPedido(cmd);
        // Etapa 2
        boolean estoqueOk = estoqueService.reservar(cmd.getItens());
        if (!estoqueOk) {
            pedidoService.cancelar(pedidoId);
            throw new EstoqueInsuficienteException();
        }
        // Etapa 3
        boolean pagamentoOk = pagamentoService.cobrar(cmd.getPagamento());
        if (!pagamentoOk) {
            estoqueService.liberar(cmd.getItens());
            pedidoService.cancelar(pedidoId);
            throw new PagamentoException();
        }
        // Sucesso: pedido concluído
    }
}

Idempotência nas Sagas

Como mensagens podem ser repetidas, cada operação deve ser idempotente (executar várias vezes tem o mesmo efeito que uma vez). Use IDs de correlação.

3. Consistência Eventual

Baseada em event sourcing ou mensageria. O sistema não garante consistência imediata. Dados podem ficar temporariamente inconsistentes (ex: estoque reservado mas pedido ainda não pago). Com o tempo, eventos eventualmente sincronizam.

Como funciona:

  • Serviço A publica evento “PedidoCriado”.
  • Serviço B (estoque) consome e reserva, publica “EstoqueReservado”.
  • Serviço C (pagamento) consome e processa, publica “PagamentoAprovado”.

Se algo falha, uma fila de retry e dead letter trata. Não há compensação explícita – o sistema eventualmente chega a um estado consistente (ex: se pagamento nunca aprova, o pedido é cancelado após timeout).

Vantagens: Alta disponibilidade, escalabilidade, baixo acoplamento.

Desvantagens: Consistência eventual não serve para tudo (ex: transferência bancária onde saldo não pode ficar negativo mesmo por segundos).

Tabela de comparação

CritérioTransações Distribuídas (2PC)SagaConsistência Eventual
ConsistênciaForte (imediata)Forte (com compensação)Fraca (eventual)
DisponibilidadeBaixa (bloqueios)AltaMuito alta
LatênciaAlta (múltiplos round trips)MédiaBaixa (assíncrona)
Complexidade de desenvolvimentoMédiaAltaMédia
Complexidade de depuraçãoMédiaAltaMédia
Tolerância a falhasBaixaMédiaAlta
Casos de uso típicosPoucos, legados financeirosE-commerce, reservas, fluxos longosNotificações, analytics, catálogos

Quando usar cada um?

Use transações distribuídas se:

  • Consistência forte imediata é obrigatória (ex: contabilidade, balanços).
  • Escala é pequena (poucas transações por segundo).
  • Você está disposto a pagar o preço da baixa disponibilidade.

Use Saga (orquestrada) se:

  • Você precisa de consistência forte, mas pode tolerar compensações.
  • O fluxo tem passos bem definidos (ex: pedido → estoque → pagamento → entrega).
  • Você precisa rastrear claramente cada transação.

Use Saga coreografada se:

  • O sistema é orientado a eventos e serviços são independentes.
  • Você não quer um orquestrador central.

Use consistência eventual se:

  • Dados inconsistentes por alguns segundos não causam dano crítico.
  • Exemplos: atualização de catálogo, envio de notificações, contagem de likes.
  • Você prioriza disponibilidade e performance.

Estratégias híbridas

Na prática, muitos sistemas combinam abordagens:

  • Partes críticas (pagamento, saldo) usam saga.
  • Partes não críticas (notificação, log) usam consistência eventual.
  • Raramente 2PC, apenas em módulos legados.

Exemplo real: e-commerce de alto volume

Um cliente da Jacobus opera um marketplace com 1 milhão de pedidos/dia. Eles usam:

  • Saga orquestrada para o fluxo principal: cria pedido, reserva estoque, processa pagamento (com chamadas síncronas a provedores externos).
  • Consistência eventual para atualização de status de entrega e notificações (Kafka + consumidores).
  • Idempotência em todos os serviços para lidar com retries.

Resultado: disponibilidade de 99,99%, zero perda de pedidos, consistência garantida no core.

Conclusão

Não há solução única para consistência em microsserviços. Transações distribuídas são frágeis. Saga é a escolha para consistência forte com compensações. Consistência eventual é perfeita para alta escala e baixo acoplamento.

Na Jacobus Software, ajudamos clientes a escolher a estratégia certa para cada domínio, desenhando arquiteturas que equilibram consistência, performance e disponibilidade.


🔄 Quer resolver o dilema da consistência no seu sistema?

Nossos arquitetos projetam sagas orquestradas, fluxos de eventos e estratégias híbridas que garantem seus dados consistentes sem sacrificar escala.

👉 Fale com a Jacobus Software

Rolar para cima