DadosAvançado9 min de leitura6 seções2000, Marco de referência: a ideia é mais velha que a data

Teorema CAP

Quando a rede parte um sistema distribuído em dois, você só pode manter uma entre consistência e disponibilidade — não as duas. O CAP não é um menu de três opções: é uma escolha forçada que só aparece durante a partição, e que a maioria dos sistemas afina por operação, não de uma vez.

Em 10 segundos

Numa partição de rede, um sistema distribuído só pode manter consistência OU disponibilidade, nunca as duas. O P (tolerância a partição) não é escolha — a rede parte de qualquer jeito —, então a decisão real é entre C e A, e só existe durante a partição. Fora dela, você tem as duas. A pergunta prática é: quando os nós não se falam, sua operação prefere recusar ou prefere responder com dado possivelmente velho?

Antes de ter nome

A tensão já era prática nos bancos distribuídos e no debate BASE × ACID dos anos 1990 — Brewer deu nome ao que a Inktomi e outros já viviam em escala.

  • #distribuido
  • #consistencia
  • #disponibilidade
  • #particao
  • #tradeoff
Analogia

Duas bilheterias e o telefone que caiu

Duas bilheterias vendem os mesmos ingressos e se ligam a cada venda para não vender a mesma poltrona duas vezes. O telefone entre elas cai. Agora cada bilheteria decide: para de vender até o telefone voltar (consistente, mas fecha a fila na porta) ou continua vendendo por conta própria (aberta, mas pode vender a poltrona 14 duas vezes). Não existe terceira opção enquanto o telefone estiver mudo — e é exatamente essa a escolha do CAP.

01Conceito

O mal-entendido de sempre

O CAP é quase sempre lido errado, como se você pudesse escolher duas letras de três — 'somos CA'. Não dá. Num sistema distribuído a partição acontece, então P está sempre em jogo; a escolha é só entre C e A durante a partição.

'Somos CA' na prática quer dizer 'não pensamos no que acontece quando a rede parte' — e a rede vai partir. O sistema então escolhe sozinho, no pior momento, e normalmente pela pior opção para aquele caso.

A segunda leitura errada é achar que a escolha é do sistema inteiro, para sempre. Não é. O mesmo banco pode servir uma operação de forma CP (a transferência que não pode duplicar) e outra de forma AP (o contador de visualizações que pode atrasar). Quóruns configuráveis — o clássico R + W > N do Dynamo — são exatamente o botão que move cada operação pelo espectro.

Vale separar CAP de um primo mais útil no dia a dia: o PACELC. Ele estende a ideia dizendo que, mesmo sem partição (o 'Else'), ainda há um trade-off entre latência e consistência — manter as réplicas perfeitamente sincronizadas custa tempo em toda escrita. Na prática, a maioria das decisões de arquitetura é sobre esse lado latência × consistência, que acontece o tempo todo, e não sobre a partição, que é rara.

Por fim, 'consistência' no CAP é a linearizabilidade — toda leitura enxerga a escrita mais recente, como se houvesse um nó só. É uma garantia muito mais forte (e cara) do que o 'C' do ACID, que fala de invariantes dentro de uma transação. Misturar os dois 'C' é a origem de metade da confusão.

02No mundo real

Como a escolha aparece na prática

O saldo que preferiu recusar

Cenário

Um sistema de pagamentos replica o saldo em três zonas de disponibilidade. Uma zona fica isolada por uma falha de rede, e chegam débitos que só ela consegue atender localmente.

Como o padrão entra

A operação de débito foi desenhada como CP: exige quórum para confirmar. Durante a partição, os débitos na zona isolada falham com erro claro e o cliente é orientado a tentar de novo — nenhum saldo fica errado.

Trade-off: Parte dos clientes vê indisponibilidade temporária justamente durante o incidente. É o preço aceito conscientemente: para dinheiro, recusar é melhor que divergir.

O carrinho que preferiu responder

Cenário

Um e-commerce guarda o carrinho de compras replicado. Durante uma partição, o mesmo usuário adiciona itens a partir de nós que não conseguem se sincronizar.

Como o padrão entra

O carrinho foi desenhado como AP, seguindo o Dynamo: aceita toda escrita e, quando a rede volta, mescla as versões (a união dos itens). O usuário nunca vê o carrinho quebrado.

Trade-off: A reconciliação pode ressuscitar um item que o usuário tinha removido nos dois lados — o famoso 'item zumbi' do Dynamo. A aplicação precisa de lógica de merge, e ela nem sempre acerta.

03Cuidado

Onde isto dá errado

  1. Dizer 'somos CA'

    Num sistema distribuído não existe abrir mão de P: a rede parte independentemente da sua vontade. 'CA' quase sempre significa 'não decidimos o que fazer na partição', e aí o sistema decide sozinho — mal — na hora do incidente.

  2. Tratar a escolha como global e permanente

    O trade-off é por operação e por configuração, não um carimbo no banco inteiro. Quóruns de leitura e escrita movem o mesmo sistema entre CP e AP; fixar 'este banco é AP' esconde os botões que realmente controlam o comportamento.

  3. Confundir o C do CAP com o C do ACID

    No CAP, consistência é linearizabilidade (toda leitura vê a última escrita); no ACID, é preservar invariantes dentro da transação. São garantias diferentes e um sistema pode ter uma sem a outra — misturá-las leva a promessas que ninguém cumpre.

  4. Otimizar para a partição e esquecer a latência

    Partição é rara; o trade-off latência × consistência (o lado 'Else' do PACELC) é diário. Manter réplicas sincronizadas em toda escrita custa tempo sempre, e é essa conta, não a da partição, que domina a experiência do usuário.

04Estrutura

A escolha na partição

Diagrama de classes
05Implementação

CP recusa; AP responde

// CAP so tem escolha DURANTE uma particao de rede.
// Fora dela, um bom sistema entrega consistencia E disponibilidade.
//
// A pergunta e: quando o no A nao consegue falar com o no B,
// e chega uma leitura, o que A faz?

// CP — recusa em vez de mentir:
async function lerCP(chave: string) {
  if (!temQuorum()) {
    throw new Error("sem quorum: nao posso garantir o valor atual");
  }
  return storage.get(chave); // so responde se tem certeza
}

// AP — responde com o que tem, e reconcilia depois:
async function lerAP(chave: string) {
  return storage.getLocal(chave); // pode estar velho; nunca recusa
}

// Nenhum dos dois e "melhor". Um extrato bancario prefere CP
// (errar o saldo e pior que esperar); um feed social prefere AP
// (mostrar um like velho e melhor que uma tela de erro).
06Decisão

Quando usar × quando evitar

Use quando

3
  • Ao escolher um banco distribuído e precisar saber como ele se comporta na partição.
  • Ao afinar quóruns de leitura e escrita por operação.
  • Ao definir, de propósito, o que cada endpoint faz quando a rede parte.

Evite quando

2
  • Aplicar a um sistema de um nó só, onde não há partição.
  • Rotular o banco inteiro de CP ou AP e ignorar a configuração.

Testar o que ficou

4 armadilhas de Teorema CAP viram perguntas, com o nome do padrão escondido, misturadas com padrões parecidos.

Onde isto aparece de verdade

Você já usa isto, talvez sem saber o nome.

  • Cassandra e DynamoDB (AP)Bancos que preferem responder com um dado possivelmente velho a recusar a escrita durante uma partição de rede.
  • etcd e ZooKeeper (CP)Sistemas de coordenação que preferem recusar a operação a devolver um valor que pode estar desatualizado.
  • quórum R + W > NO botão que move um mesmo banco pelo espectro: quóruns altos compram consistência pagando disponibilidade e latência.

O padrão em uma linha

Sem nome de domínio, sem cerimônia. Só a ideia.

// Sob partição, escolha: consistência ou disponibilidade.
// Na prática: timeout curto + degradar leitura.

O que ele cobra

Nenhum salto a mais entre a chamada e o efeito.

  • Obriga a decidir, por operação, o que fazer durante uma partição — e a maioria dos times nunca decide isso conscientemente
  • O lado AP empurra a reconciliação de conflitos para a aplicação, que agora precisa saber mesclar versões divergentes
  • O lado CP transforma partição de rede em indisponibilidade visível, que precisa de timeout e retry para não travar o cliente

Não vale se: o sistema roda numa máquina só. Sem rede entre réplicas não há partição, e o CAP simplesmente não se aplica ao seu problema.

Onde isto aparece

Continue por aqui