Consistencia, CAP y PACELC | Nicolás Garzón
Consistencia no es una propiedad binaria ni una etiqueta de producto. Describe qué relaciones entre operaciones puede observar un cliente cuando existen concurrencia, réplicas, retrasos y fallos de red.
Decir que un sistema es “consistente” no basta. Puede significar:
Que una lectura ve la escritura más reciente.
Que varias transacciones producen un resultado equivalente a ejecutarse una por una.
Que las réplicas convergen eventualmente.
Que un usuario siempre ve sus propios cambios.
Que los efectos respetan causalidad.
Estas garantías responden preguntas distintas.
La arquitectura debe elegirlas por operación y explicar su costo.
Texto
Copiar operación de negocio
+ daño de observar un estado antiguo
+ costo de coordinar
+ tolerancia a indisponibilidad
→ garantía de consistenciaSupón que un cliente confirma un pedido y recibe éxito. Después consulta el historial y el pedido no aparece porque la lectura fue dirigida a una réplica retrasada.
Desde la base, ambas respuestas pueden ser técnicamente válidas bajo replicación eventual. Desde la experiencia del usuario, el sistema parece haber perdido información.
Dos cajeros leen una unidad disponible.
Ambos confirman venta.
Las réplicas convergen después.
Aunque exista convergencia, la invariante de inventario ya se rompió.
La consistencia necesaria depende del significado del dato, no solo de la tecnología.
Imagina todas las operaciones como una historia.
Texto
Copiar A: write stock = 9
B: read stock
C: write stock = 8Un modelo de consistencia define qué órdenes y resultados están permitidos.
No describe únicamente el estado final. Describe qué puede observar cada actor durante la ejecución.
Una operación linearizable parece ocurrir en un único instante entre su inicio y su finalización.
Si una escritura termina antes de que comience una lectura, la lectura debe observarla.
Texto
Copiar write(x = 10) termina
↓
read(x) comienza
↓
debe devolver 10 o un valor posterior
Modelo intuitivo parecido a una única copia.
Lecturas recientes.
Coordinación adecuada para locks, líderes o registros críticos.
Comunicación entre nodos.
Mayor latencia.
Menor disponibilidad durante una partición.
Dependencia de quorum, líder o reloj/protocolo correcto.
Linearizability se aplica a operaciones individuales sobre objetos o registros. No garantiza por sí sola que una transacción con varias operaciones sea serializable.
Serializability describe transacciones. El resultado debe ser equivalente a alguna ejecución serial, aunque internamente se ejecuten concurrentemente.
Texto
Copiar T1 y T2 concurrentes
→ resultado equivalente a T1 después T2
o T2 después T1Protege invariantes que dependen de varias lecturas y escrituras.
Dos transacciones verifican que exista al menos un encargado activo y cada una desactiva uno diferente. Cada fila puede ser linearizable y aun así la invariante global quedar rota si no existe serializability adecuada.
Concepto Pregunta principal Ámbito Linearizability ¿La operación respeta tiempo real? Operaciones sobre objetos Serializability ¿Las transacciones equivalen a un orden serial? Varias lecturas y escrituras
Una base puede ofrecer transacciones serializables sobre una copia sin que lecturas desde réplicas remotas sean linearizables.
Combina serializability con orden de tiempo real. Es un modelo fuerte y cómodo, pero costoso en sistemas distribuidos.
No siempre es necesario para todo el producto. Puede reservarse para operaciones críticas.
Si no ocurren nuevas escrituras, todas las réplicas convergen eventualmente.
Texto
Copiar write en réplica A
→ propagación
→ B y C todavía antiguas
→ con tiempo suficiente, A = B = CConvergencia bajo las condiciones del sistema.
Cuánto tarda.
Qué valores intermedios se observan.
Read-your-writes.
Ausencia de conflictos.
Orden global.
Que una invariante de negocio se conserve.
“Eventual” sin un límite o expectativa operativa es una garantía insuficiente para diseñar UX y alertas.
Puede definirse una tolerancia:
Menos de 5 segundos.
Menos de 100 versiones.
Dentro de la misma sesión.
Hasta que termine una reconciliación.
Esto permite conectar la consistencia con SLO y experiencia de usuario.
Si una operación B depende de A, todos deben observar A antes que B.
Usuario publica un comentario.
Otro responde al comentario.
Un lector no debería ver la respuesta sin el comentario original.
No ordena eventos independientes. Evita romper relaciones de causa y efecto con menos coordinación que un orden global.
Son útiles para experiencia de usuario.
Un usuario ve sus propias escrituras.
Después de observar una versión nueva, no vuelve a una más antigua.
Sus escrituras se aplican en el orden emitido.
Una escritura posterior a una lectura se aplica sobre una versión al menos tan reciente como la observada.
Estas garantías pueden implementarse con afinidad, tokens de versión, lectura de líder o espera por posición de réplica.
Los lectores observan un prefijo válido del log, no eventos fuera de orden.
Texto
Copiar A, B, C publicados
válido: A
válido: A, B
inválido: A, C sin BEs importante en streams y proyecciones.
CAP se aplica cuando existe una partición de red entre nodos que deben coordinar una operación.
Durante esa partición, para esa operación, el sistema no puede garantizar simultáneamente:
Consistencia linearizable.
Disponibilidad para cada solicitud en nodos no fallidos.
La partición no es una preferencia decorativa. En un sistema distribuido debe considerarse posible.
Un lado rechaza o bloquea operaciones para evitar divergencia.
Consecuencia: algunas solicitudes no reciben respuesta útil.
Ambos lados responden y pueden divergir.
Consecuencia: se necesitan conflictos, convergencia o semántica tolerante.
CAP no significa elegir dos letras para siempre.
Qué ocurre sin partición.
Cuánta latencia existe.
Qué operaciones son AP o CP.
Cómo se resuelven conflictos.
Qué consistencia de sesión existe.
Qué durabilidad ofrece el sistema.
Un producto puede comportarse distinto según operación, configuración o nivel de quorum.
PACELC amplía la pregunta:
Texto
Copiar si hay partición (P)
→ disponibilidad (A) o consistencia (C)
else, en operación normal (E)
→ latencia (L) o consistencia (C)Incluso sin fallos, coordinar réplicas para una lectura reciente añade latencia. Leer localmente responde más rápido, pero puede devolver estado antiguo.
W: confirmaciones requeridas para escribir.
R: respuestas requeridas para leer.
La condición R + W > N crea intersección matemática entre lectura y escritura.
Texto
Copiar N = 3
W = 2
R = 2Al menos una réplica de lectura participó en la escritura.
Puede fallar la expectativa de consistencia si existen:
Versiones concurrentes.
Sloppy quorums.
Nodos que responden con datos antiguos.
Relojes inconsistentes.
Reparación incompleta.
Escrituras que no se ordenan correctamente.
El sistema debe reconciliar versiones, no solo contar respuestas.
Conserva el valor con timestamp mayor.
Relojes desincronizados.
Pérdida silenciosa de intención.
Una escritura antigua puede ganar.
No es adecuado para todas las reglas.
Representan qué versiones conocen otras versiones y permiten detectar concurrencia.
El sistema puede saber si una escritura reemplaza a otra o si ambas son concurrentes.
El dominio decide cómo combinar.
Agregar productos puede unirse.
Cambiar dirección de entrega puede requerir conflicto visible.
Estructuras diseñadas para converger matemáticamente sin coordinación para operaciones específicas.
Contadores.
Sets.
Registros con reglas de merge.
No resuelven cualquier invariante. Un contador convergente no evita vender stock negativo si la regla exige límite global.
No todo el sistema necesita el mismo modelo.
Necesita evitar sobreventa. Puede requerir coordinación fuerte dentro de una frontera.
El estado final necesita autoridad y reconciliación con proveedor. Una respuesta incierta debe quedar pending, no inventar éxito o fallo.
El usuario espera read-your-writes. Otros usuarios podrían tolerar propagación breve.
Puede aceptar staleness de segundos o minutos si precios críticos se validan al comprar.
Puede operar con retraso explícito de minutos u horas.
Pueden ser at-least-once e idempotentes; no deben definir la verdad del pedido.
Supón dos regiones que aceptan ventas del mismo inventario.
Todas las reservas coordinan con una región principal.
Invariante simple.
Menos conflictos.
Latencia interregional.
Menor disponibilidad si la región principal no puede alcanzarse.
Cada región recibe una porción del stock.
Texto
Copiar stock total 100
→ región A: 60
→ región B: 40Cada región reserva localmente. Transferir cuota requiere coordinación.
Baja latencia local.
Disponibilidad regional.
Capacidad fragmentada.
Rebalanceo.
Posible stock libre en una región y agotado en otra.
Ambas venden y reconcilian después.
Para inventario físico suele ser inaceptable porque la compensación implica cancelar pedidos.
La arquitectura depende del daño de la inconsistencia.
La interfaz debe representar incertidumbre.
pending.
processing.
confirmed.
failed.
requires_review.
Texto
Copiar cliente envía pago
→ timeout
→ estado pending
→ webhook o reconciliación
→ confirmed / failedMostrar error definitivo tras un timeout puede provocar que el usuario repita y cobre dos veces.
Cuando la coordinación inmediata no existe, se necesita corregir divergencias.
Comparar fuente de verdad y proyección.
Detectar registros ausentes o antiguos.
Reaplicar eventos o consultar autoridad.
Registrar corrección.
Alertar si excede tolerancia.
La reconciliación no debe ser un script improvisado solo durante incidentes.
Un usuario observa una versión anterior. Monotonic reads se rompe. Usa version tokens, líder o bloqueo hasta alcanzar posición.
Una proyección recibe OrderCancelled antes de OrderConfirmed. Usa versión de agregado y rechaza o difiere eventos antiguos.
Dos regiones cambian el mismo campo. LWW puede perder una actualización válida. Define merge o autoridad.
La cola de conflictos crece. El sistema necesita límite, degradación o bloqueo antes de superar capacidad de reconciliación.
Timestamps no representan causalidad confiable. Usa relojes lógicos, secuencias o autoridad.
La transacción puede ser fuerte en un nodo, pero las lecturas desde réplicas seguir siendo stale.
“Elegimos AP” no explica operaciones, conflictos, staleness ni UX.
Eleva costo innecesariamente. Define por capacidad y flujo.
La UI muestra éxito o fallo cuando el resultado es incierto. Produce duplicados y pérdida de confianza.
Las réplicas pueden converger en un valor que viola el negocio.
Pierde intención sin evidencia. Diseña autoridad o merge de dominio.
Genera operaciones concurrentes y verifica que los resultados cumplen el modelo esperado.
Aísla nodos y observa qué operaciones responden o fallan.
Introduce retraso y comprueba read-your-writes y monotonic reads.
Crea escrituras concurrentes y verifica resolución.
Elimina o altera una proyección y demuestra reconstrucción.
Lag por réplica.
Edad de datos.
Conflictos pendientes.
Tiempo de convergencia.
Reconciliaciones fallidas.
Lecturas enviadas a líder.
La invariante es crítica.
Compensar es costoso o imposible.
El volumen permite coordinación.
Existe autoridad clara.
Ejemplos: reservas limitadas, saldos, permisos críticos.
El dato es derivado.
La demora es tolerable y explícita.
Existe reconstrucción.
Los conflictos pueden resolverse.
La disponibilidad o latencia local tiene valor importante.
Ejemplos: búsqueda, analítica, notificaciones, feeds.
Consistencia describe historias observables, no solo estado final.
Linearizability y serializability resuelven problemas distintos.
Eventual consistency no define cuánto tarda ni qué se ve durante la convergencia.
CAP aplica durante particiones y por operación.
PACELC recuerda el trade-off normal entre latencia y coordinación.
Quorums requieren versionado y reparación.
La UX debe representar incertidumbre.
Las garantías deben elegirse según daño de inconsistencia.
¿Puede una base ser serializable y devolver lecturas stale desde réplicas?
¿Por qué R + W > N no garantiza automáticamente linearizability?
¿Qué diferencia existe entre convergencia y conservación de una invariante?
¿Cómo ofrecerías read-your-writes sin enviar todas las lecturas al líder para siempre?
¿Cuándo sería razonable dividir stock en cuotas regionales?
Ver respuestas orientativas
Sí. Las transacciones del líder pueden ser serializables mientras una réplica todavía no aplica cambios.
Porque importan versiones, concurrencia, sloppy quorums y resolución, no solo la intersección.
Convergencia hace que copias terminen iguales; la invariante exige que el valor resultante sea válido para el negocio.
Mediante afinidad temporal, token de posición, espera de réplica o lectura del líder hasta que la réplica alcance la versión.
Cuando la baja latencia regional importa y el stock puede repartirse sin desperdicio o riesgo inaceptable.
Latencia, throughput y percentiles conecta estas decisiones de coordinación con el costo que perciben usuarios y sistemas bajo carga.