Saltar al contenido

055 — CAP, PACELC y lo que realmente se elige

🗂️ parte 🎚️ nivel ⏱️ duración 📗 clase

Programa · Parte 10 · ← Anterior · Siguiente →

Parte 10 — Distribución, réplica y consistencia · Avanzado · 3 horas estimadas · motores cassandra, spanner, postgresql · laboratorio labs/05-nosql-workloads · 4 fuentes.

Conceptos centrales: partición de red · disponibilidad · latencia frente a consistencia

En este caso se comparan 7 motores: 6 lo resuelven (0 con el resultado comprobado por máquina) y 1 no, con el motivo escrito.

De qué trata esta clase

CAP dicho con precisión y despojado de la versión de póster. La disponibilidad del teorema es mucho más estricta que el «99,9 % de tiempo activo» del lenguaje operativo, y confundirlas es el origen de casi todas las lecturas erróneas. PACELC añade lo que CAP calla: el compromiso entre latencia y consistencia existe también los días en que no hay avería.

flowchart LR
    C["🗄️ Clase 055"]
    C --> K1["partición de red"]
    C --> K2["disponibilidad"]
    C --> K3["latencia frente a consistencia"]
    classDef raiz fill:#0b3d2e,stroke:#3fb950,color:#fff
    class C raiz

Antes de empezar

Esta clase supone que ya trabajaste lo siguiente. Si algo de la última columna no te suena, vuelve a esa clase antes de seguir: aquí se usa sin volver a explicarlo.

# Clase previa Lo que se da por sabido
053 Réplica: líder único, multilíder y sin líder replicación sincrónica · retraso de réplica · quórum · lectura de tu propia escritura

Vocabulario de la clase

Los términos que siguen se usan más adelante con este significado exacto. La definición completa, con sus términos relacionados, está en el glosario del programa.

Término Qué significa Procedencia
partición de red Situación en la que dos grupos de nodos siguen vivos pero no pueden comunicarse. No es un fallo hipotético: es lo que ocurre con un cable, un cortafuegos mal aplicado o una latencia lo bastante alta como para que los tiempos de espera venzan. se introduce aquí
disponibilidad En el enunciado formal de CAP, que toda petición a un nodo no caído reciba respuesta. Es una definición mucho más estricta que el «99,9 % de tiempo activo» del lenguaje operativo, y confundirlas es el origen de casi todas las lecturas erróneas del teorema. se introduce aquí
latencia frente a consistencia La mitad de PACELC que CAP ignora: incluso sin particiones hay que elegir entre responder rápido desde una réplica cercana o esperar la coordinación que garantiza el dato más reciente. Es el compromiso que se paga todos los días, no solo el día de la avería. se introduce aquí

Propósito

Enunciar CAP con precisión, entender por qué su lectura popular es engañosa y usar PACELC, que describe mejor el compromiso que se toma todos los días.

Resultados de aprendizaje

Al terminar podrás:

  1. Enunciar el teorema CAP con las definiciones exactas de sus términos.
  2. Explicar por qué «elegir dos de tres» es una lectura incorrecta.
  3. Aplicar PACELC y situar motores reales en su clasificación.
  4. Determinar qué garantías sobreviven a una partición.
  5. Decidir el comportamiento de tu sistema durante una partición, por operación.

Fundamentos

El enunciado preciso

Gilbert y Lynch (2002) demostraron formalmente la conjetura de Brewer. Los términos tienen definiciones estrictas que casi nunca se citan:

Teorema: ningún sistema distribuido puede garantizar las tres simultáneamente.

Por qué «dos de tres» está mal

La red se particiona. No es una opción de diseño: es un hecho del mundo. Renunciar a P significaría suponer que la red nunca falla, lo cual no es un sistema distribuido sino una apuesta.

Por tanto la elección real es binaria y solo durante la partición:

Brewer lo aclaró él mismo en 2012: el teorema se aplica en el instante de la partición y las tres propiedades son continuas, no binarias. Además, la mayor parte del tiempo no hay partición, y ahí CAP no dice nada. Ese vacío es lo que PACELC llena.

PACELC

Abadi (2012):

if (P) then (A or C)      -- durante una partición: disponibilidad o consistencia
else     (L or C)         -- en operación normal: latencia o consistencia

La segunda mitad es la que gobierna el 99,9 % del tiempo. Cada confirmación sincrónica a otra región cuesta una ida y vuelta: entre Santiago y Fráncfort, unos 200 ms. Ese costo se paga siempre, no solo cuando algo falla.

Sistema Con partición Sin partición Clasificación
PostgreSQL (líder único, síncrono) C C PC/EC
PostgreSQL (líder único, asíncrono) C en el líder L PC/EL
Cassandra (ONE) A L PA/EL
Cassandra (QUORUM) Configurable C PC/EC
DynamoDB (eventual) A L PA/EL
DynamoDB (fuerte) C C PC/EC
MongoDB (majority) C C PC/EC
Spanner C C PC/EC

Dos observaciones que cambian la conversación:

  1. La clasificación es por operación, no por producto. Cassandra es AP o CP según el nivel de consistencia de cada consulta.
  2. Spanner es PC/EC y aun así ofrece alta disponibilidad, porque usa redes privadas con particiones extremadamente raras y consenso rápido (clase 047). No viola CAP: elige C y su disponibilidad práctica es alta porque P casi nunca ocurre.

Qué sobrevive a una partición

Bailis et al. clasifican qué garantías son alcanzables manteniendo la disponibilidad total:

Garantía ¿Disponible bajo partición?
Consistencia eventual
Lectura de tus escrituras Sí (con sesión fijada)
Lectura monótona
Consistencia causal
Aislamiento de instantánea No
Serializabilidad No
Linealizabilidad No

La frontera es nítida: todo lo que exige un orden total acordado necesita coordinación, y la coordinación es lo primero que una partición rompe. Todo lo demás —incluida la consistencia causal, que es bastante fuerte— se puede sostener sin coordinar.

flowchart TD
    P{"¿Hay partición<br/>de red?"}
    P -- "Sí" --> A{"¿Responder con datos<br/>posiblemente obsoletos?"}
    A -- "Sí" --> AP["AP: disponible,<br/>inconsistente"]
    A -- "No" --> CP["CP: rechaza o espera,<br/>consistente"]
    P -- "No (99,9 % del tiempo)" --> L{"¿Coordinar en cada<br/>operación?"}
    L -- "Sí" --> EC["EC: consistente,<br/>+latencia por ida y vuelta"]
    L -- "No" --> EL["EL: rápido,<br/>consistencia más débil"]

Ejemplo trabajado

Plataforma educativa con nodos en Santiago y Fráncfort. La red entre regiones se corta 4 minutos.

Operación 1 — leer el catálogo de cursos.

Datos que cambian una vez al día. Servir la versión de hace unos minutos no daña a nadie.

Decisión: AP. Se sirve desde la réplica local aunque esté desconectada.
Consecuencia: un curso creado hace 3 minutos en Santiago no se ve en Fráncfort.
Aceptable: sí, y se documenta.

Operación 2 — inscribir en un curso con cupo limitado.

Si ambas regiones aceptan inscripciones sin coordinarse, el cupo se excede.

Decisión: CP. Durante la partición, la región sin quórum rechaza.
Consecuencia: 4 minutos sin inscripciones en Fráncfort.
Aceptable: sí. Peor sería vender 50 plazas de un curso de 40.

Operación 3 — registrar una nota.

Escritura de un solo autor por par (estudiante, curso). No hay conflicto posible.

Decisión: AP con consistencia causal. Se acepta localmente y se reconcilia después.
Consecuencia: la nota tarda en verse en la otra región.
Aceptable: sí, porque no hay dos escritores compitiendo por el mismo dato.

La tabla que resulta, y que es el entregable de esta clase:

Operación Con partición Justificación Coste declarado
Leer catálogo A Datos casi estáticos Hasta 5 min de desfase
Inscribir con cupo C Recurso finito compartido Indisponible en la minoría
Registrar nota A Un solo escritor por clave Visibilidad diferida
Autenticar A Credenciales replicadas, cambios raros Un cambio de contraseña puede tardar
Cambiar contraseña C Seguridad: no puede quedar la antigua Indisponible en la minoría

Y el lado «else», que se paga siempre. Sin partición, la inscripción con QUORUM entre regiones cuesta:

ida y vuelta Santiago-Fráncfort ≈ 200 ms
inscripción con quórum global   ≈ 200 ms añadidos por operación

Ese es el EC de PACELC, y es la razón por la que casi todos los sistemas globales acaban con datos regionales: la inscripción se coordina solo dentro de la región del curso, no globalmente. Eso convierte una decisión de consistencia global en una local, y es el diseño que de verdad se usa.

Comparación

Situación Clasificación adecuada
Sesiones y preferencias PA/EL
Catálogo de productos PA/EL
Inventario con reserva PC/EC
Movimientos contables PC/EC
Métricas y telemetría PA/EL
Autenticación (lectura) PA/EL
Cambio de credenciales PC/EC

Errores frecuentes

  1. «Elegimos AP» como decisión de producto. Es por operación, no por sistema.
  2. Renunciar a P. La red se particiona; no es opcional.
  3. Usar «consistencia» de CAP y de ACID como sinónimos. Son cosas distintas: linealizabilidad frente a restricciones de integridad.
  4. Ignorar el lado «else». El costo de latencia se paga siempre, la partición casi nunca.
  5. Suponer que un producto tiene una clasificación fija. Depende del nivel de consistencia elegido.
  6. Coordinar globalmente lo que podría coordinarse por región.

De la clase a la operación

La pregunta útil en una revisión de arquitectura no es «¿somos CP o AP?», sino «¿qué hace exactamente cada operación durante una partición, y quién decidió que eso era aceptable?». Esa tabla, escrita, vale más que cualquier etiqueta.

Reto de transferencia

  1. Enumera las operaciones críticas de tu sistema.
  2. Decide para cada una A o C durante la partición, con justificación de negocio.
  3. Calcula el costo de latencia del lado «else» en tu topología real.
  4. Identifica una operación que hoy se coordina globalmente y podría hacerlo por región.

Preguntas de evaluación

  1. Enuncia CAP con las definiciones exactas de C, A y P.
  2. ¿Por qué Spanner puede ser PC/EC y tener alta disponibilidad práctica?
  3. Da una operación de tu sistema que hoy es AP sin que nadie lo haya decidido.
  4. ¿Qué garantías transaccionales son inalcanzables manteniendo disponibilidad total?

🌐 El mismo problema en cada motor

Caso: Qué se elige de verdad cuando se dice «elegimos AP» o «elegimos CP»

El teorema CAP dice algo muy concreto y muy limitado: cuando la red se parte, un sistema no puede ser a la vez consistente —en el sentido de linealizable— y disponible. Nada más. No dice que haya que elegir dos de tres, ni describe el comportamiento normal del sistema, que es el 99,9 % del tiempo.

Por eso Abadi propuso PACELC, que completa la frase: si hay partición (P), se elige entre disponibilidad (A) y consistencia (C); y si no (E, else), se elige entre latencia (L) y consistencia (C). La segunda mitad es la que manda casi siempre, y es la que las etiquetas «AP» y «CP» esconden.

Aquí se compara qué elige cada motor en las dos mitades, y —lo más útil— qué se puede ajustar por operación en vez de por sistema.

Esta comparación es conceptual: la decisión no se reduce a una consulta con resultado, así que aquí no hay sello de máquina. Lo que se compara es lo que cada motor ofrece y a qué precio, con la página oficial al lado de cada afirmación.

Motor ¿Resuelve el caso? Nivel de prueba Código Fuente
Apache Cassandra conceptual doc oficial
MongoDB conceptual doc oficial
PostgreSQL conceptual doc oficial
Google Cloud Spanner conceptual doc oficial
CockroachDB conceptual doc oficial
Redis conceptual doc oficial
SQLite no doc oficial

Los que resuelven el caso

Apache Cassandra

MongoDB

PostgreSQL

Google Cloud Spanner

CockroachDB

Redis

Los que no resuelven este caso — y qué se hace en su lugar

Descartar un motor con un argumento es tan formativo como usarlo. Ninguna de estas filas dice que el motor sea peor: dice que este problema no es el suyo.

Motor Por qué no Qué se hace en su lugar Fuente
SQLite Un solo proceso y un solo archivo: no hay red que se pueda partir, así que el teorema no dice nada sobre él. Incluirlo aquí sería usar el vocabulario sin el problema. La pregunta análoga en un sistema de un solo nodo es otra —qué pasa si se corta la luz— y se estudia en la clase de registro anticipado y recuperación. doc

Laboratorio

python scripts/validate_repository.py
python labs/05-nosql-workloads/run_nosql_lab.py

Guarda como evidencia la salida completa, la versión del motor y la semilla o los parámetros usados. Una captura sin comando no es evidencia: no se puede repetir.

Evaluación

Criterio Peso Qué se comprueba
Comprensión conceptual 25 % Explica el mecanismo, no solo el resultado
Ejecución reproducible 25 % Otra persona obtiene lo mismo con las instrucciones dadas
Interpretación basada en evidencia 25 % Cada conclusión se apoya en una salida o una medición
Límites y riesgos declarados 25 % Dice qué no demuestra el ejercicio y qué faltaría en producción

La clase se da por superada cuando la respuesta explica el mecanismo, muestra la salida que la respalda y declara al menos un límite del ejercicio.

Fuentes de esta clase

Todo lo afirmado arriba procede de estas obras. Los identificadores viven en catalog/sources.json y el estado de los enlaces se comprueba con python scripts/check_external_links.py.


Programa · Parte 10 · ← Anterior · Siguiente →