← Back to home

O dilema da computação

By Pscodium · 8/4/2026 · 3 views

O Dilema da Computação — Teorema CAP, CP vs AP e PACELC

Quando começamos a estudar sistemas distribuídos, existe uma pergunta que aparece constantemente:

É possível construir um sistema que seja consistente, disponível e tolerante a falhas de rede ao mesmo tempo?

A resposta, de acordo com o Teorema CAP, é que, diante de uma partição de rede, não é possível garantir simultaneamente as três propriedades.

Esse conceito foi proposto por Eric Brewer em 2000 e posteriormente provado formalmente por Seth Gilbert e Nancy Lynch em 2002.

O CAP é um dos conceitos fundamentais de System Design, porque ajuda a entender por que bancos de dados distribuídos precisam fazer escolhas difíceis.

Porém, existe um problema.

Muitas explicações apresentam o CAP como:

Escolha 2:

C — Consistency
A — Availability
P — Partition Tolerance

Essa explicação é didática, mas pode ser enganosa.

Na prática, o verdadeiro dilema aparece quando ocorre uma partição de rede.

É nesse momento que precisamos escolher entre:

CP

ou:

AP

E entender essa diferença é fundamental para projetar sistemas distribuídos.


1. O que é o Teorema CAP?

CAP representa três propriedades:

C — Consistency
A — Availability
P — Partition Tolerance

Em português:

Consistência
Disponibilidade
Tolerância a Partições

A ideia central é:

Em um sistema distribuído, quando ocorre uma partição de rede, não é possível garantir simultaneamente consistência forte e disponibilidade total.

Isso significa que:

P acontece
    │
    ▼
Escolha entre
    │
    ├── C
    │
    └── A

Ou seja:

CP

ou:

AP

2. Por que o CAP existe?

Para entender o CAP, precisamos primeiro entender que sistemas distribuídos dependem de comunicação entre máquinas.

Imagine:

             DATABASE
                 │
        ┌────────┴────────┐
        ▼                 ▼
     Server A          Server B

Os servidores precisam conversar:

Server A ◄────────► Server B

Mas redes podem falhar.

Podemos ter:

Server A       X       Server B

A conexão entre os dois servidores foi perdida.

Agora temos:

┌─────────────┐      X      ┌─────────────┐
│  Server A   │             │  Server B   │
│             │             │             │
│  Dados A    │             │  Dados B    │
└─────────────┘             └─────────────┘

Os dois servidores continuam funcionando.

Porém, eles não conseguem mais se comunicar.

Isso é uma:

Network Partition

Ou simplesmente:

Partição de rede.


3. O que significa Consistency?

No contexto do CAP, Consistency não significa simplesmente "os dados estão corretos".

O conceito é mais específico.

Uma definição simplificada é:

Toda leitura recebe o valor mais recente ou um erro.

Imagine:

Banco
Saldo = R$ 100

Executamos:

UPDATE saldo
SET saldo = 50

Depois disso:

WRITE → saldo = 50

Se o sistema possui consistência forte:

READ
  │
  ▼
R$ 50

Não deveríamos receber:

R$ 100

de uma réplica que ainda não foi atualizada.

A consistência forte tenta garantir que os clientes tenham uma visão coerente dos dados.


4. O que significa Availability?

Availability significa que toda requisição recebida por um nó disponível deve receber uma resposta.

Imagine:

Server A
   │
   ▼
Request
   │
   ▼
Resposta

Mesmo que outro servidor esteja indisponível:

Server A        X        Server B
   │                     │
   ▼                     X
Resposta              Indisponível

O Server A continua respondendo.

O sistema prioriza:

Continuar funcionando.

Mesmo que isso signifique que diferentes clientes possam temporariamente observar dados diferentes.


5. O que significa Partition Tolerance?

Partition Tolerance significa que o sistema consegue continuar operando mesmo quando existe uma falha de comunicação entre partes da rede.

Imagine:

        REDE
          │
          X
          │
   ┌──────┴──────┐
   │             │
   ▼             ▼
Server A      Server B

A comunicação entre os dois lados falhou.

Um sistema tolerante a partições consegue continuar funcionando de alguma maneira.

Isso é extremamente importante porque, em sistemas distribuídos reais:

Partições de rede são inevitáveis.

Cabos falham.

Switches falham.

Roteadores falham.

Datacenters ficam isolados.

Regiões inteiras podem perder conectividade.

Portanto, na prática, sistemas distribuídos precisam considerar P.


6. O famoso "escolha 2 de 3"

É comum encontrar este diagrama:

             Consistency
                 /\
                /  \
               /    \
              /      \
             /        \
            /          \
           /            \
          /              \
 Availability ─────────── Partition

E ouvir:

"Você precisa escolher dois dos três."

Essa explicação é útil para iniciantes, mas é uma simplificação enganosa.

O problema é que ela sugere que podemos simplesmente escolher:

C + A

e abandonar:

P

Mas em um sistema distribuído real, não podemos simplesmente escolher ignorar partições.

Quando dois servidores não conseguem se comunicar, precisamos lidar com essa situação.

Por isso, a discussão real é:

Quando ocorre uma partição:

    CP
     ou
    AP

O P é praticamente obrigatório em sistemas distribuídos.

A verdadeira escolha acontece entre:

Consistência
      vs
Disponibilidade

durante uma partição.


7. A situação crítica: Network Partition

Imagine duas réplicas:

             REDE
               │
        ┌──────┴──────┐
        ▼             ▼
    Replica A      Replica B

Ambas possuem:

Saldo = R$ 100

Agora ocorre uma partição:

Replica A       X       Replica B

Um cliente conecta na Replica A:

Cliente A
    │
    ▼
Replica A
    │
    ▼
Saldo = R$ 100

Outro cliente conecta na Replica B:

Cliente B
    │
    ▼
Replica B
    │
    ▼
Saldo = R$ 100

Agora:

Cliente A
    │
    ▼
Replica A
    │
    ▼
- R$ 50

A Replica A agora possui:

Saldo = R$ 50

Enquanto a Replica B ainda possui:

Saldo = R$ 100

A rede continua particionada.

Agora chega outro cliente:

Cliente C
    │
    ▼
Replica B

O que o sistema deve fazer?

A Replica B pode:

Aceitar a operação

Ou:

Recusar a operação

Aqui está o dilema.


8. Escolha CP

CP significa:

Consistency
+
Partition Tolerance

Quando ocorre uma partição, o sistema prefere manter consistência, mesmo que precise rejeitar algumas requisições.

Imagine:

Replica A       X       Replica B

O sistema não consegue confirmar o estado global.

Então:

Request
   │
   ▼
Não é possível garantir consistência
   │
   ▼
Rejeitar

Resultado:

Consistência → Mantida
Disponibilidade → Reduzida

Em outras palavras:

É melhor retornar um erro do que retornar uma resposta potencialmente incorreta.


9. Exemplo CP

Imagine um sistema bancário.

Temos:

Conta
Saldo = R$ 1.000

O usuário tenta transferir:

R$ 1.000

Agora existe uma partição:

Datacenter A       X       Datacenter B

Se o sistema não consegue confirmar o estado da conta, ele pode decidir:

TRANSFERÊNCIA
    │
    ▼
Não é possível garantir consistência
    │
    ▼
ERRO

O usuário recebe:

Operação temporariamente indisponível.

Isso é muito melhor do que permitir:

Conta A
Saldo = -R$ 1.000

ou:

Transferência duplicada

Nesse caso, consistência é mais importante do que disponibilidade.


10. Escolha AP

AP significa:

Availability
+
Partition Tolerance

Nesse modelo, durante uma partição, o sistema continua respondendo.

Mesmo que diferentes nós tenham informações diferentes.

Imagine:

Replica A       X       Replica B

A Replica A recebe:

WRITE
Produto X
Estoque = 10

A Replica B ainda possui:

Estoque = 11

Mesmo assim, ela pode continuar respondendo.

O sistema prioriza:

Disponibilidade

em vez de consistência imediata.

Quando a rede voltar:

Replica A
    │
    │ sincronização
    ▼
Replica B

O sistema tenta reconciliar os dados.

Isso é conhecido como:

Eventual Consistency


11. Consistência Forte

Em um sistema de consistência forte:

WRITE
  │
  ▼
Atualização confirmada
  │
  ▼
READ
  │
  ▼
Novo valor

Exemplo:

Valor inicial = 100

Executamos:

WRITE = 50

Depois:

READ

Resultado:

50

O sistema garante que as leituras posteriores observem a atualização confirmada.


12. Consistência Eventual

Na consistência eventual, diferentes réplicas podem temporariamente possuir valores diferentes.

Imagine:

            WRITE = 50
                │
                ▼
             Primary
                │
       ┌────────┴────────┐
       ▼                 ▼
   Replica A          Replica B
       │                 │
     50                  100

Durante algum tempo:

Replica A = 50
Replica B = 100

Depois:

Replica A = 50
Replica B = 50

O sistema convergiu.

A ideia é:

Se nenhuma nova atualização ocorrer, eventualmente todas as réplicas convergirão para o mesmo estado.


13. Eventual Consistency não significa "dados errados"

Isso é importante.

Eventual consistency não significa que o sistema é inconsistente para sempre.

Significa que:

Agora:
Replica A = X
Replica B = Y

Mas:

Futuro:
Replica A = X
Replica B = X

Existe uma janela de inconsistência.

Essa janela pode durar:

Milissegundos
Segundos
Minutos

Dependendo da arquitetura.


14. Split-Brain

Um problema particularmente perigoso é o chamado:

Split-Brain

Imagine um cluster:

        Cluster
           │
    ┌──────┴──────┐
    ▼             ▼
 Node A          Node B

Ocorre uma partição:

Node A       X       Node B

Agora os dois lados podem acreditar que estão autorizados a operar.

Por exemplo:

Node A:
"Eu sou o líder!"

Node B:
"Não, eu sou o líder!"

Temos:

        SPLIT-BRAIN

      ┌─────────┐
      │ Node A  │
      │ LEADER  │
      └─────────┘

          X

      ┌─────────┐
      │ Node B  │
      │ LEADER  │
      └─────────┘

Agora ambos aceitam escritas.

Podemos ter:

Node A
User 123 → saldo 100


Node B
User 123 → saldo 50

Quando a rede volta:

????

Qual é o valor correto?

Esse é um dos motivos pelos quais sistemas distribuídos precisam de mecanismos de:

  • Eleição de líder
  • Quorum
  • Consensus
  • Fencing
  • Detecção de falhas

15. Quorum

Uma técnica comum para evitar problemas de consistência é utilizar quorum.

Imagine:

3 réplicas

Podemos exigir:

2 confirmações

Para uma operação ser considerada válida.

Por exemplo:

Replica A ✓
Replica B ✓
Replica C ✗

Temos:

2 de 3

A operação pode ser confirmada.

Isso reduz o risco de dois lados isolados acreditarem que possuem autoridade suficiente.


16. O verdadeiro trade-off: CP vs AP

Quando ocorre uma partição:

NETWORK PARTITION
       │
       ▼
┌──────┴──────┐
│             │
▼             ▼
CP            AP

CP

Prioriza:

Consistência

Se não conseguir garantir consistência:

Retorna erro

Exemplo conceitual:

Request
   │
   ▼
Não posso confirmar
   │
   ▼
ERROR

AP

Prioriza:

Disponibilidade

Mesmo sem comunicação completa:

Request
   │
   ▼
Processa
   │
   ▼
Sincroniza depois

Pode resultar em:

Eventual Consistency

17. MongoDB

O MongoDB é um banco orientado a documentos.

Sua arquitetura moderna utiliza:

Replica Set

Por exemplo:

              PRIMARY
                 │
        ┌────────┴────────┐
        ▼                 ▼
    SECONDARY         SECONDARY

Em condições normais, temos:

Write
  │
  ▼
Primary

As operações são replicadas.

Se o Primary falhar:

Primary
   X

Os nós restantes podem realizar uma eleição:

Secondary
    │
    ▼
Novo Primary

O MongoDB permite diferentes níveis de preocupação com consistência e durabilidade através de configurações como:

Read Concern
Write Concern
Read Preference

Portanto, classificá-lo simplesmente como:

MongoDB = CP

é uma simplificação.

O comportamento depende da configuração e do padrão de operação.

Em muitos cenários de replicação, o MongoDB prioriza consistência e eleição de um líder, mas oferece opções que permitem diferentes trade-offs.

O ponto importante é:

Sistemas reais não são simplesmente "CAP = X". O comportamento depende da configuração e da operação analisada.


18. Cassandra

O Cassandra foi projetado para alta disponibilidade e escalabilidade horizontal.

Sua arquitetura é distribuída:

       Node 1
      /      \
     /        \
Node 2 ───── Node 3

Ele não depende de um único Primary da mesma forma que arquiteturas tradicionais.

Durante uma partição, o Cassandra pode continuar aceitando operações em diferentes nós.

Isso favorece:

Availability

e:

Partition Tolerance

Portanto, é frequentemente associado ao modelo:

AP

O Cassandra utiliza mecanismos como:

  • Replicação
  • Quorum
  • Consistency Levels
  • Eventual Consistency

Por exemplo:

ONE
QUORUM
ALL

O nível escolhido altera o trade-off entre:

Latência
Consistência
Disponibilidade

19. DynamoDB

O Amazon DynamoDB é um banco distribuído projetado para alta disponibilidade e escalabilidade.

Ele utiliza replicação interna e permite diferentes comportamentos de leitura.

Podemos ter:

Eventually Consistent Reads

ou:

Strongly Consistent Reads

Isso significa que o DynamoDB não deve ser reduzido a:

DynamoDB = AP

O comportamento depende do tipo de operação e da configuração.

A arquitetura do DynamoDB prioriza fortemente:

Alta disponibilidade
Escalabilidade
Baixa latência

Enquanto oferece opções de consistência para diferentes necessidades.


20. Spanner

O Google Spanner é um exemplo interessante.

Ele foi projetado para oferecer:

Escalabilidade global
+
Consistência forte

Isso é extremamente difícil em sistemas distribuídos geograficamente.

O Spanner utiliza mecanismos sofisticados de sincronização e consenso.

Uma característica conhecida é o uso do:

TrueTime

que permite ao sistema trabalhar com uma noção de tempo global suficientemente precisa para suportar ordenação de eventos e transações distribuídas.

O Spanner mostra que:

CAP não diz que consistência forte e disponibilidade são impossíveis em sistemas distribuídos.

O que o CAP diz é que, durante uma partição de rede, você não consegue garantir simultaneamente as propriedades de consistência e disponibilidade definidas pelo teorema.

Um sistema pode oferecer:

Consistência forte
+
Escalabilidade global

mas ainda precisar sacrificar disponibilidade durante uma partição.

Portanto, o Spanner é frequentemente associado a:

CP

21. CouchDB

O CouchDB possui uma arquitetura baseada em replicação e sincronização.

Um de seus diferenciais históricos é permitir que diferentes nós trabalhem de maneira relativamente independente e sincronizem posteriormente.

Imagine:

Node A
   │
   X
   │
Node B

Ambos podem continuar operando.

Depois:

Node A
   │
   │ Sync
   ▼
Node B

Isso favorece:

Availability
+
Partition Tolerance

E utiliza conceitos relacionados à:

Eventual Consistency

Esse modelo pode ser útil para aplicações que precisam funcionar mesmo quando os dispositivos estão temporariamente offline.


22. Comparando exemplos

Uma visão simplificada:

SistemaTendênciaCaracterísticaMongoDBCP em muitos cenáriosReplica Sets e eleiçãoCassandraAPAlta disponibilidade e distribuiçãoDynamoDBAP/ajustávelLeituras consistentes ou eventuaisSpannerCPConsistência forte em escala globalCouchDBAPReplicação e sincronização

Essa tabela não deve ser interpretada como uma classificação absoluta.

O comportamento real depende de:

  • Configuração
  • Tipo de operação
  • Modelo de replicação
  • Nível de consistência
  • Quorum
  • Topologia
  • Tipo de falha

23. CAP não é sobre "qual banco é melhor"

Imagine:

Banco A
CP

Banco B
AP

Isso não significa:

A é melhor
B é pior

Significa apenas:

Problema diferente
    │
    ▼
Trade-off diferente

Se temos:

Sistema financeiro

podemos preferir:

CP

Se temos:

Rede social

podemos aceitar:

AP

Por exemplo:

Número de curtidas

Pode ser eventualmente consistente.

Mas:

Transferência bancária

provavelmente exige garantias muito mais fortes.


24. PACELC

O CAP explica o que acontece:

DURANTE UMA PARTIÇÃO

Mas existe uma pergunta importante:

E quando a rede está funcionando normalmente?

Mesmo sem uma partição, sistemas distribuídos ainda precisam escolher entre:

Latência

e:

Consistência

É aí que entra o:

PACELC

A sigla significa:

P — Partition
A — Availability
C — Consistency

E — Else

L — Latency
C — Consistency

A ideia pode ser resumida assim:

Se houver Partição (P)
    │
    └── escolher entre A ou C

Caso contrário (E)
    │
    └── escolher entre L ou C

Ou:

P → A ou C
ELSE → L ou C

25. Por que o PACELC é importante?

Imagine dois sistemas.

Ambos são:

CP

Ou seja, ambos priorizam consistência durante uma partição.

Mas, em condições normais, eles podem ter comportamentos diferentes.

Sistema A:

Mais consistente
Mais lento

Sistema B:

Menos latência
Mais complexo para manter consistência

O CAP não explica completamente essa diferença.

O PACELC explica.

Sistema distribuído

        PARTIÇÃO?
          │
     ┌────┴────┐
    SIM       NÃO
     │          │
     ▼          ▼
   A ou C      L ou C

26. Exemplo prático do PACELC

Imagine uma aplicação global:

Brasil
   │
   ▼
Servidor Brasil

EUA
   │
   ▼
Servidor EUA

Os dados precisam ser replicados:

Brasil ─────────► EUA

Agora temos uma escolha.

Podemos esperar confirmação de ambos:

Brasil
   │
   ▼
EUA
   │
   ▼
Confirmação

Isso aumenta a consistência.

Porém:

Latência ↑

Ou podemos responder imediatamente:

Brasil
   │
   ▼
Resposta

E replicar depois:

Brasil
   │
   │ async
   ▼
EUA

Isso reduz:

Latência ↓

Mas pode resultar em:

Consistência eventual

Esse é exatamente o tipo de trade-off que o PACELC ajuda a visualizar.


27. CAP vs PACELC

CAP:

Durante uma partição:

C
vs
A

PACELC:

Durante uma partição:

C
vs
A

Sem partição:

C
vs
L

Podemos representar:

              SISTEMA DISTRIBUÍDO
                     │
            ┌────────┴────────┐
            │                 │
        PARTIÇÃO           NORMAL
            │                 │
            ▼                 ▼
          C vs A            C vs L

Essa é uma visão muito mais completa.


28. O verdadeiro dilema da computação distribuída

O grande insight é que:

Distribuir dados aumenta a capacidade do sistema, mas também aumenta a complexidade.

Quando distribuímos:

Server 1
Server 2
Server 3

ganhamos:

Escalabilidade
Disponibilidade
Tolerância a falhas

Mas precisamos lidar com:

Latência
Consistência
Partições
Sincronização
Conflitos
Eleição de líder
Consensus

Cada benefício vem acompanhado de um custo.


29. Uma forma prática de pensar

Ao projetar um sistema, faça estas perguntas:

1. O que acontece se a rede falhar?

2. Posso continuar respondendo?

3. Posso aceitar dados temporariamente inconsistentes?

4. Preciso de consistência forte?

5. Qual é a latência aceitável?

6. O usuário prefere erro ou dado temporariamente antigo?

7. Posso resolver conflitos posteriormente?

Essas respostas ajudam a definir:

CP

ou:

AP

E depois:

PACELC

30. Exemplos de decisões

Sistema bancário

Consistência > Disponibilidade

Preferência:

CP

Se não podemos garantir o saldo correto:

Retornamos erro

Rede social

Disponibilidade > Consistência imediata

Podemos aceitar:

Eventual Consistency

Uma curtida pode demorar alguns segundos para aparecer em todos os lugares.


Contador de visualizações

Podemos aceitar:

AP

Uma pequena diferença entre réplicas não é crítica.


Sistema de pagamentos

Precisamos de:

Consistência forte
Idempotência
Transações

O sistema não pode processar duas vezes o mesmo pagamento.


Aplicação offline-first

Podemos aceitar:

AP
+
Eventual Consistency

O dispositivo continua funcionando offline.

Quando a conexão volta:

Sincronização
    │
    ▼
Resolução de conflitos

31. Resumo visual

                    CAP
                     │
                     ▼
             Ocorreu partição?
                     │
              ┌──────┴──────┐
             SIM           NÃO
              │              │
              ▼              ▼
            C vs A         CAP não
                           explica tudo
                              │
                              ▼
                            PACELC
                              │
                              ▼
                            C vs L

32. Resumo final

CAP

O Teorema CAP afirma que:

Durante uma partição de rede, um sistema distribuído não consegue garantir simultaneamente consistência e disponibilidade.


CP

Prioriza:

Consistency
+
Partition Tolerance

Durante uma partição:

Pode rejeitar requisições

Ideal para operações onde dados incorretos são inaceitáveis.


AP

Prioriza:

Availability
+
Partition Tolerance

Durante uma partição:

Continua respondendo

Pode aceitar:

Eventual Consistency

Ideal quando disponibilidade é mais importante que consistência imediata.


Consistência Forte

WRITE
  │
  ▼
READ
  │
  ▼
Novo valor

Consistência Eventual

WRITE
  │
  ├── Replica A → Novo valor
  │
  └── Replica B → Valor antigo
                    │
                    ▼
                  Sync
                    │
                    ▼
              Mesmo valor

PACELC

O CAP fala sobre:

Partição:
C vs A

O PACELC adiciona:

Sem partição:
C vs L

Ou seja:

P → A ou C
ELSE → L ou C

Conclusão

O Teorema CAP não é uma regra que diz:

"Escolha dois entre três."

Essa é apenas uma forma simplificada de introduzir o conceito.

A realidade é mais interessante.

Em um sistema distribuído, partições de rede são inevitáveis. Quando elas acontecem, precisamos decidir se o sistema deve:

CP

ou:

AP

Se escolhermos consistência, podemos precisar sacrificar disponibilidade.

Se escolhermos disponibilidade, podemos aceitar consistência eventual.

Mas o dilema não termina quando a rede está funcionando.

Mesmo em condições normais, sistemas distribuídos precisam decidir entre:

Consistência

e:

Latência

É por isso que o PACELC é uma extensão tão importante do CAP.

No final, o verdadeiro trabalho de um arquiteto de sistemas não é escolher:

"CAP = CP"

ou:

"CAP = AP"

O verdadeiro trabalho é entender o negócio e responder:

"Quais inconsistências meu sistema pode tolerar?"

"Quanto tempo meu sistema pode ficar indisponível?"

"Qual latência é aceitável?"

"O que acontece quando dois usuários modificam o mesmo dado ao mesmo tempo?"

"É melhor retornar um erro ou um dado potencialmente desatualizado?"

Essas perguntas definem a arquitetura.

E esse é o verdadeiro dilema da computação distribuída:

         CONSISTÊNCIA
              ▲
              │
              │
              │
              └──────────────► DISPONIBILIDADE

                    +
                   
                  LATÊNCIA

Não existe uma solução perfeita para todos os sistemas.

Existem apenas trade-offs.

E entender esses trade-offs é uma das habilidades mais importantes em System Design.


Comments

No comments yet.