ENGENHARIA DE SOFTWARE · LEITURA DE ~10 MIN
Padrões de Consistência
em Sistemas Distribuídos
Dois clientes compram o último exemplar do mesmo livro ao mesmo tempo. Qual serviço "ganha"? A resposta certa depende de um único fator: qual padrão de consistência o sistema escolheu — e essa escolha muda tudo sobre como ele se comporta sob pressão.
SEÇÃO 01
O que é um sistema distribuído
Antes de falar de consistência, vale alinhar uma ideia simples: um sistema distribuído é uma aplicação dividida em várias partes, cada uma rodando separado, que conversam entre si pela rede para entregar um resultado só.
Pega uma livraria online como exemplo. Em vez de um único servidor cuidando de tudo, a aplicação pode ser dividida assim:
Cada serviço tem uma responsabilidade e, muitas vezes, o seu próprio banco de dados. Isso já foi coberto em detalhe no artigo sobre microsserviços na prática — aqui o interesse é outro: o que acontece com os dados quando eles ficam espalhados assim.
A definição mais citada é da Wikipédia: um sistema distribuído é um conjunto de componentes localizados em computadores diferentes na rede, que se comunicam e coordenam suas ações trocando mensagens entre si, para atingir um objetivo em comum.
SEÇÃO 02
Por que consistência é um problema
Quando os dados vivem em mais de um lugar, alguém precisa garantir que essas cópias não fiquem contando histórias diferentes. Volta pro exemplo da livraria: o Serviço de Estoque precisa saber, com precisão, quantos exemplares de um livro ainda existem no momento em que alguém tenta comprar.
Agora imagine dois clientes olhando pro mesmo livro — só resta 1 exemplar — ao mesmo tempo:
Isso é uma condição de corrida clássica: entre o momento em que o Cliente B lê o estoque e o momento em que o Serviço de Estoque termina de processar a compra do Cliente A, a informação ficou desatualizada — e ninguém percebeu a tempo.
É exatamente esse tipo de problema que os padrões de consistência resolvem: eles definem quando, exatamente, uma escrita feita em um lugar se torna visível para uma leitura feita em outro.
SEÇÃO 03
As três famílias de padrões
Não existe uma resposta universal para "quando os dados devem sincronizar" — existe uma troca (trade-off) entre três coisas: quão rápido o sistema responde, quão disponível ele fica quando algo falha, e quão exata é a informação que ele entrega. Os padrões de consistência são as três formas mais comuns de fazer essa troca:
Repare que consistência eventual não é uma terceira categoria independente — é um caso específico, e bem comportado, de consistência fraca: ela não promete nada sobre quando a leitura vai refletir a escrita, só promete que, sem novas escritas, todas as cópias convergem pro mesmo valor com o tempo.
SEÇÃO 04
Consistência forte
Aqui a regra é simples de enunciar: depois que uma escrita termina, qualquer leitura seguinte — não importa de qual réplica — vê essa escrita imediatamente. Pra isso funcionar, a replicação precisa ser síncrona: todas as cópias são atualizadas antes de o sistema confirmar que a operação terminou.
Um sistema financeiro é o exemplo clássico: ninguém pode ver o saldo de uma conta "quase" atualizado. O preço dessa garantia é claro — como o sistema precisa esperar todas as réplicas confirmarem antes de responder, ele tem latência mais alta e fica menos disponível quando uma réplica está fora do ar.
Essa troca tem nome: o Teorema CAP diz que, durante uma falha de rede entre réplicas (uma partição), um sistema distribuído só consegue manter duas de três garantias — Consistência, Disponibilidade e Tolerância a Partição. Como partição de rede é inevitável em produção, na prática a escolha real é entre consistência e disponibilidade quando as coisas dão errado. Consistência forte escolhe consistência; os outros dois padrões deste artigo escolhem disponibilidade.
SEÇÃO 05
Consistência fraca
Aqui a promessa é bem mais solta: depois de uma escrita, uma leitura seguinte pode ver essa mudança — ou pode não ver. Não existe garantia de prazo nem de ordem. Isso soa arriscado, mas é exatamente o que faz sentido quando velocidade importa mais do que precisão absoluta.
Numa plataforma de jogos multiplayer, as ações de um jogador aparecem na hora pra quem está no mesmo servidor. Se alguém tiver uma perda momentânea de conexão, essa pessoa pode não ver certas ações a tempo — e o jogo não trava esperando por isso. Isso gera inconsistência real entre o que cada jogador enxerga, mas também é o que permite alta disponibilidade e baixa latência, que é o que realmente importa numa partida em tempo real.
SEÇÃO 06
Consistência eventual
Consistência eventual pega a ideia de consistência fraca e adiciona uma promessa a mais: sem novas escritas chegando, todas as réplicas eventualmente convergem para o mesmo valor. A replicação acontece de forma assíncrona — o sistema responde antes de propagar a mudança pra todo mundo.
Uma rede social é o exemplo mais intuitivo: os dados moram em vários datacenters ao redor do mundo, pensados pra alta disponibilidade e baixa latência. Quando alguém posta algo, essa atualização aparece na hora pra quem está no mesmo datacenter, mas leva um tempinho pra propagar pros outros. Durante essa janela, pessoas diferentes literalmente enxergam versões diferentes do mesmo feed — e isso é uma escolha de design, não um bug.
Na prática, "eventualmente" costuma vir com reforços: leitura de quórum (exigir resposta de N de M réplicas antes de considerar uma leitura válida, reduzindo a chance de ler um dado velho) e consistência causal (garantir que, se uma escrita depende de outra — como uma resposta que só faz sentido depois do comentário original —, a ordem entre as duas é respeitada, mesmo sem consistência forte no resto do sistema).
SEÇÃO 07
Comparando os três padrões
Colocando lado a lado, fica mais claro o que cada padrão troca pelo quê:
Repare que nenhuma linha dessa tabela é "melhor" de forma absoluta — cada uma é a certa pra um tipo de problema diferente. É por isso que sistemas grandes de verdade quase sempre misturam os três padrões, cada um aplicado numa parte diferente da arquitetura.
SEÇÃO 08
Como escolher na prática
Antes de escolher um padrão, três perguntas ajudam a diagnosticar o que o dado realmente exige:
- Um dado errado causa prejuízo real? Saldo de conta, estoque final de um pagamento único, permissão de acesso — isso pede consistência forte.
- O sistema pode ficar fora do ar esperando sincronizar? Se a resposta for não, alguma forma de consistência fraca ou eventual costuma ser necessária.
- Um pequeno atraso na propagação é aceitável? Curtidas, contagem de visualizações, feed de posts — quase sempre toleram consistência eventual sem ninguém notar.
Vale lembrar que essa escolha não precisa ser única para o sistema inteiro. Na própria livraria do início do artigo, o pagamento pode exigir consistência forte, enquanto a contagem de "quantas pessoas visualizaram esse livro hoje" tranquilamente aceita consistência eventual.
SEÇÃO 09
Conclusão
Consistência não é uma caixa de "sim ou não" — é um espectro, e cada ponto dele custa algo diferente:
Consistência forte:
troca velocidade e disponibilidade por exatidão garantida.
Consistência fraca:
troca exatidão por velocidade e alta disponibilidade.
Consistência eventual:
aceita atraso temporário, mas garante que tudo converge.
A pergunta certa nunca é "qual padrão de consistência é o melhor" — é "o que esse dado específico não pode se dar ao luxo de errar, e o que ele pode se dar ao luxo de esperar". Responder isso, dado por dado, é o que separa uma arquitetura distribuída bem pensada de uma que só parece funcionar até o dia em que dois pedidos chegam ao mesmo tempo.
FIM · OBRIGADO POR LER
Quer ver essas decisões aplicadas num sistema inteiro?
O artigo de System Design mostra como cache, banco de dados e comunicação assíncrona se encaixam nas mesmas trocas de consistência, disponibilidade e latência discutidas aqui.