Home Comunidade Eventos YouTube Networks Desafios // produtos Academy News CTI | CVE Contato

02 - Consistência vs Disponibilidade (CAP Theorem)

#cap#consistencia#pacelc#replicacao#sagas
video explicativo
Video explicativoEspaco reservado para o video desta anotação — adicione video: https://youtu.be/... no frontmatter da nota.

Consistência versus Disponibilidade (CAP Theorem)

O teorema CAP estabelece que um sistema de dados distribuído não pode garantir, ao mesmo
tempo, consistência linearizável, disponibilidade total e tolerância a partição de rede.
Eric Brewer formulou a conjectura em 2000 a partir de experiência operacional, e Seth
Gilbert e Nancy Lynch a demonstraram formalmente em 2002. Consistência, no sentido do
teorema, significa que toda leitura retorna a escrita mais recente, como se existisse uma
única cópia dos dados; disponibilidade significa que todo nó não falho responde a toda
requisição, sem erro; tolerância a partição significa que o sistema continua operando mesmo
com a rede dividida. A leitura popular de "escolha dois" induz a erro: em produção
distribuída, a partição é inevitável, então a tolerância a ela não é opcional. A escolha
real acontece no momento da partição, entre responder com dado possivelmente obsoleto e
recusar operação.

O que o teorema realmente afirma

Durante uma partição, o sistema deve escolher entre dois comportamentos para a mesma chave.
Um sistema CP preserva consistência e recusa ou atrasa operações nos nós que não conseguem
confirmar a maioria: prefere indisponibilidade parcial a dado incorreto. Um sistema AP
preserva disponibilidade e responde com a cópia local, aceitando que cópias divirjam até a
partição cicatrizar; a recuperação exige resolução de conflito, por versão, por timestamp ou
por semântica de mesclagem.

Fora da partição, o teorema não impõe restrição, e essa é a nuance prática central: a
diferença entre CP e AP é sobre o comportamento durante o incidente, e não sobre qualidade
geral do produto. Desenhar bem significa decidir explicitamente, por dado e por operação,
qual resposta é aceitável quando a rede se parte. A decisão precisa estar registrada,
testada e conhecida por quem opera, e não descoberta durante o incidente.

Partições são a norma, não a exceção

Em escala, falha de rede é evento de operação cotidiana, e não cenário remoto. Partição
inclui não só o cabo cortado, mas qualquer perda ou atraso de mensagem: pausa de garbage
collection que faz o nó parecer morto, saturação de rede entre zonas, reinício de switch,
timeout agressivo mal calibrado e DNS instável. Sistemas com milhares de nós observam
partições diárias, e desenhar como se a rede fosse confiável é apostar em sorte com dados
reais. A consequência de projeto é tratar partição como caso de teste obrigatório: exercitar
cenários de rede lenta e dividida, definir comportamento por operação durante a partição e
garantir que a cicatrização não perca escrita aceita. A pergunta de arquitetura muda de "e
se a rede falhar?" para "quando a rede falhar, o que cada operação devolve?".

Testar partição é disciplina de engenharia de caos. Feche a rede entre dois nós em
ambiente de estágio, meça o que cada operação devolve e verifique se a cicatrização
reconverge sem perda; repita em produção com escopo controlado e raio de explosão limitado.
Sem esse teste, a escolha CP ou AP é apenas intenção, e intenção não aparece no gráfico do
incidente.

PACELC: o else também decide

O teorema CAP silencia sobre o comportamento fora da partição, e o PACELC preenche essa
lacuna: se houver partição (P), escolha entre disponibilidade e consistência; senão (E),
escolha entre latência (L) e consistência (C). A replicação síncrona compra consistência com
latência, porque a escrita espera confirmação da réplica; a assíncrona compra latência com
risco de leitura obsoleta. Essa segunda escolha é a mais frequente no dia a dia, e é onde a
maioria dos sistemas realmente opera. Um banco relacional com commit confirmado em réplica
síncrona paga latência a cada escrita; com replicação assíncrona, ganha latência e assume o
risco de escrita perdida se a primária cair antes de replicar. A lição operacional: monitore
o atraso de replicação como métrica de primeira classe, porque ele define a janela de
inconsistência percebida pelo usuário.

Sistemas CP e AP na prática

A classificação ajuda a entender a expectativa de cada tecnologia sob partição. Do lado CP,
etcd, ZooKeeper e Consul preservam verdade única de configuração e coordenação, aceitando
perda de disponibilidade para a maioria; CockroachDB e bancos NewSQL mantêm transações
serializáveis com consenso; MongoDB com escrita em maioria e HBase preferem consistência
sobre disponibilidade. Do lado AP, Cassandra, DynamoDB, Riak e CouchDB continuam aceitando
escrita e leitura durante a partição e resolvem a divergência depois; a semântica resultante
é eventualmente consistente, com conflito resolvido por versão ou por política de mesclagem.

A escolha segue a natureza do dado, e não a preferência tecnológica. Carrinho de compras e
sessão de usuário toleram divergência temporária e pedem AP; livro razão financeiro,
permissões e coordenação de líder não toleram divergência e pedem CP. O erro clássico é
inverter os dois: exigir CP do carrinho, e perder vendas em blip de rede; exigir AP do
razão, e aceitar saldo divergente.

Sagas e compensação como saída prática

Transações distribuídas por two-phase commit não são a resposta padrão em arquitetura de
serviços: o coordenador vira ponto de bloqueio, e uma partição durante o protocolo trava
recursos dos dois lados. A saída consolidada é a saga: sequência de transações locais em que
cada passo tem uma compensação definida, e a falha de um passo dispara a execução reversa
dos passos anteriores. Em um pedido, reservar estoque, cobrar cartão e emitir nota são
passos locais; se o pagamento falha, a compensação libera o estoque reservado.

A saga pode ser coreografada, em que cada serviço reage a eventos do anterior, ou
orquestrada, com um coordenador explícito do fluxo. A coreografia reduz acoplamento e
dificulta o rastreio do fluxo; a orquestração tem o comportamento inverso. Pré-condições
obrigatórias em qualquer formato: idempotência em cada passo, para sobreviver à reentrega de
mensagem; padrão outbox para publicar o evento na mesma transação do dado; e compensações
idempotentes e auditáveis, porque elas também falham e também são reexecutadas.

# Saga orquestrada simplificada: cada passo tem compensação explícita.
def processar_pedido(pedido):
    reservar_estoque(pedido)          # passo 1: transação local
    try:
        cobrar_cartao(pedido)         # passo 2: transação local
    except PagamentoRecusado:
        liberar_estoque(pedido)       # compensação do passo 1
        registrar_falha(pedido)       # observabilidade do fluxo
        raise
    emitir_nota_com_retry(pedido)     # passo 3: tolerante, retry assíncrono

Escolha por operação, e não por produto

A decisão CP ou AP não precisa ser monolítica. Muitos sistemas oferecem consistência
ajustável: em Cassandra, leitura e escrita por quórum, com a condição R + W > N garantindo
sobreposição de réplicas, enquanto leitura de um único nó prioriza latência; em DynamoDB, a
leitura fortemente consistente custa mais latência e throughput que a eventual. Outro
desenho recorrente é o escritor único por chave, que elimina conflito de escrita e
simplifica a ordenação, deixando a replicação assíncrona cuidar da leitura. Para a
experiência do usuário, padrões de leitura também ajudam: read-your-writes com roteamento
para a réplica que atendeu a escrita, ou sessão afixada por usuário. No nível de sistema, a
arquitetura por células limita o raio de explosão de uma partição, e cada célula opera de
forma independente, com sincronização definida entre elas.

Uma regra de bolso útil para revisão de desenho: liste as três operações de escrita mais
críticas do produto e responda, para cada uma, o que acontece com a partição em curso. Se
alguma resposta for desconhecida, o desenho ainda não terminou.

Erros comuns e boas práticas

  • Tratar a partição como exceção teórica: projete e teste o comportamento de cada operação sob rede dividida e lenta.
  • Copiar a escolha CP ou AP de outro produto sem avaliar o dado: classifique por domínio, e não por empresa alheia.
  • Ignorar o PACELC fora do incidente: o atraso de replicação é janela de inconsistência e precisa de métrica e alerta.
  • Implementar saga sem idempotência: a reentrega de mensagem duplica cobrança ou libera estoque duas vezes.
  • Usar two-phase commit entre serviços: bloqueio sob partição e coordenador como ponto único anulam a autonomia dos serviços.
  • Confundir consistência eventual com ausência de conflito: defina política de resolução por versão, timestamp ou mesclagem, com teste do conflito real.

Comparativo de comportamento

A tabela resume as expectativas operacionais de cada orientação, do comportamento durante a
partição ao caso de uso típico.

Característica Sistema CP Sistema AP
Resposta durante partição Recusa ou atrasa operação sem maioria Responde com cópia local
Semântica de leitura Sempre a escrita mais recente Pode retornar dado obsoleto
Resolução de conflito Evitada por consenso Necessária pós-cicatrização
Exemplos etcd, ZooKeeper, CockroachDB Cassandra, DynamoDB, Riak
Caso típico Coordenação, permissões, razão Carrinho, sessão, perfil
Custo fora de partição Latência de consenso Latência baixa, consistência eventual