← dev-notes
DIST · PARTE 1 DE 2

CAP, Consistencia
y Modelos de Fallo

El trilema que define toda decisión en sistemas distribuidos — qué sacrificas y cuándo

DIST · P1
⚖ CAP Theorem 📐 PACELC 🔄 Modelos de consistencia 🧪 BASE vs ACID 💥 Modos de fallo
01 CAP Theorem
BREWER 2000 · EL TRILEMA FUNDAMENTAL
TEOREMA 01
En presencia de una partición de red (P), un sistema distribuido solo puede garantizar Consistencia (C) o Disponibilidad (A), nunca ambas simultáneamente. Formulado por Eric Brewer (2000) y probado formalmente por Gilbert y Lynch (2002).
C
Consistency
Todos los nodos ven los mismos datos al mismo tiempo. Cada lectura devuelve la escritura más reciente o un error.
A
Availability
Todo request recibe una respuesta (sin garantía de que sea la más reciente). El sistema no retorna errores.
P
Partition Tolerance
El sistema continúa operando aunque se pierdan mensajes o falle la comunicación entre nodos.
P no es opcional en producción
La partición de red siempre puede ocurrir en un sistema distribuido real. Elegir "CA" (sin P) solo es posible en sistemas monolíticos con una sola copia de datos — lo que no es un sistema distribuido. En la práctica la pregunta es: ante una partición, ¿sacrifico C o A?
Tipo Garantías Ante partición Ejemplos Cuándo elegirlo
CP Consistencia + Tolerancia a partición Retorna error o bloquea en lugar de devolver dato desactualizado ZooKeeper, etcd, HBase, CockroachDB Coordinación, locks distribuidos, configuración crítica
AP Disponibilidad + Tolerancia a partición Responde con dato potencialmente desactualizado Cassandra, DynamoDB, CouchDB, Riak Carritos de compra, contadores, feeds, alta disponibilidad prioritaria
CA Consistencia + Disponibilidad No aplica — asume red sin particiones RDBMS tradicional (MySQL, PostgreSQL sin replicación) Sistema single-node; inaplicable en distribución real
02 PACELC — el modelo extendido
ABADI 2012 · LA PREGUNTA QUE CAP NO RESPONDE
EXTENSIÓN DE CAP
PACELC
CAP solo describe el comportamiento durante una partición. PACELC (Daniel Abadi, 2012) completa el cuadro: incluso cuando no hay partición, existe un trade-off entre Latencia (L) y Consistencia (C).
if Partitionchoose C or A
else Latency vs Consistency
PA/EL — Cassandra: AP en partición, baja latencia en operación normal
PC/EC — HBase, ZooKeeper: CP en partición, consistencia fuerte siempre
PA/EC — MongoDB: AP en partición, pero consistencia fuerte cuando hay quórum
PC/EL — DynamoDB DAX: CP en partición, pero baja latencia via cache
El insight de PACELC: la consistencia siempre tiene un costo. En sistemas de baja latencia, incluso sin fallo de red, forzar consistencia fuerte requiere coordinación que añade latencia.
03 Modelos de consistencia
DEL MÁS FUERTE AL MÁS DÉBIL
ESPECTRO DE CONSISTENCIA
No existe solo "consistente" o "eventual". Hay un espectro: más fuerte = más costoso en latencia y disponibilidad. Conocer estos modelos permite diseñar sistemas con las garantías exactas que el negocio necesita — ni más ni menos.
NIVEL 5 · MÁS FUERTE
Linearizabilidad
El sistema se comporta como si tuviera una sola copia. Las operaciones son instantáneas y globalmente ordenadas. Máximo costo en latencia.
ZooKeeper, etcd, Spanner
NIVEL 4
Consistencia secuencial
Todos los nodos ven el mismo orden de operaciones, pero no necesariamente en tiempo real. El orden global existe, pero puede haber lag.
Algunos RDBMS replicados
NIVEL 3
Consistencia causal
Las operaciones causalmente relacionadas son vistas en orden. Operaciones independientes pueden verse en cualquier orden. Equilibrio entre consistencia y latencia.
MongoDB causal sessions, COPS
NIVEL 2
Read-your-writes
Garantía mínima de sesión: después de escribir, siempre ves tu propia escritura. No implica nada sobre lo que ven otros nodos.
DynamoDB strongly consistent reads
NIVEL 1 · MÁS DÉBIL
Consistencia eventual
Dadas suficientes actualizaciones, eventualmente todas las réplicas convergen al mismo valor. No hay garantía de cuándo.
Cassandra, DynamoDB (default), Redis replicado
Confundir "eventual consistency" con "sin consistencia". Eventual consistency sigue siendo un contrato — solo dice que la convergencia ocurre, no cuándo. Un sistema sin ninguna garantía es simplemente incorrecto.
04 BASE vs ACID en sistemas distribuidos
EL CAMBIO DE CONTRATO AL ESCALAR
ACID es el contrato de las bases de datos relacionales clásicas. Cuando escalamos horizontalmente, mantener ACID completo se vuelve prohibitivamente costoso. BASE es el contrato alternativo que adoptan la mayoría de sistemas distribuidos de alta escala.
ACID
Bases de datos relacionales · Transacciones locales
A
Atomicity (Atomicidad)
Todo o nada. La transacción se completa entera o se revierte completamente. No hay estados intermedios.
C
Consistency (Consistencia)
La BD pasa de un estado válido a otro estado válido. Las restricciones y reglas siempre se cumplen.
I
Isolation (Aislamiento)
Las transacciones concurrentes no se interfieren. El resultado es el mismo que si hubieran corrido en serie.
D
Durability (Durabilidad)
Una vez commitida, la transacción persiste aunque falle el sistema. Garantizada por WAL y fsync.
BASE
Sistemas distribuidos · Alta disponibilidad
B
Basically Available
El sistema siempre responde, aunque algunos nodos fallen o los datos no sean los más recientes. Disponibilidad sobre correctitud instantánea.
S
Soft State
El estado del sistema puede cambiar con el tiempo incluso sin input externo, debido a la propagación eventual entre réplicas.
E
Eventually Consistent
Si no hay nuevas escrituras, eventualmente todas las réplicas convergen al mismo valor. No se garantiza cuándo — solo que ocurrirá.
Implicación práctica
El código de aplicación debe manejar lecturas potencialmente stale, idempotencia en escrituras y conflictos de versiones.
05 Modos de fallo en sistemas distribuidos
LO QUE PUEDE SALIR MAL · Y SALE
Un sistema distribuido falla de formas imposibles en un monolito. Entender los modos de fallo es prerequisito para diseñar con resiliencia.
🔌
Partición de red
Dos grupos de nodos no pueden comunicarse entre sí. Cada grupo puede seguir operando localmente — pero sus estados divergen. Es el escenario que CAP modela.
→ Cassandra: ambos lados siguen aceptando escrituras. Luego reconcilia con anti-entropy.
🧠
Split Brain
Dos nodos creen ambos ser el líder / primary simultáneamente. Pueden aceptar escrituras inconsistentes. Causa corrupción si no hay protocolo de desempate.
→ Solución: quórum, fencing tokens, STONITH en clusters.
Fallo silencioso (Crash-stop)
Un nodo deja de responder sin enviar ningún mensaje de error. El resto no sabe si está lento o muerto. Timeout + heartbeat son la única forma de detectarlo.
→ Comportamiento default de la mayoría de sistemas. Manejado con timeouts y health checks.
🎭
Fallo Bizantino
Un nodo se comporta de forma arbitraria y maliciosa: envía mensajes incorrectos, contradictorios o selectivos a diferentes nodos. Es el caso más difícil.
→ Requiere BFT (Byzantine Fault Tolerance). Solo necesario en contextos adversariales (blockchain, finanzas críticas).
🕰
Clock Skew
Los relojes de distintos nodos no están perfectamente sincronizados. Usar timestamps para ordenar eventos es inherentemente inseguro. NTP solo reduce — no elimina — el skew.
→ Solución: relojes lógicos (Lamport) o TrueTime (Google Spanner). Ver Parte 2.
📦
Mensajes duplicados / reordenados
TCP garantiza entrega en orden dentro de una conexión, pero no entre múltiples nodos o tras reconexión. Los sistemas de mensajería (Kafka, RabbitMQ) pueden duplicar mensajes ante fallos.
→ Solución: idempotencia en consumidores + sequence numbers o deduplication IDs.
🔗
Conexión con el código Java/Spring
Cada uno de estos fallos tiene una respuesta en código: Circuit Breaker (crash-stop), idempotency keys (mensajes duplicados), distributed locks con fencing (split brain), relojes lógicos (clock skew). Los patrones de resiliencia de la tarjeta siguiente son la respuesta práctica a estos fallos teóricos.