La arquitectura se centra en un secuenciador de transacciones determinista que ordena las operaciones utilizando Relojes Lógicos Híbridos en lugar de tiempo físico, eliminando las dependencias de sesgo de reloj inherentes a los sistemas basados en TrueTime. El coordinador implementa una variante del protocolo Calvin, donde las intenciones de transacción se replican a la mayoría de los líderes de fragmentos antes de la ejecución, asegurando la serialización a través de una programación determinista en lugar de bloqueo distribuido. Las especificaciones de TLA+ modelan las transiciones de estado del coordinador, verificando formalmente que el sistema mantiene la seguridad (serialización estricta) y la vivacidad (todas las transacciones confirmadas eventualmente se completan) incluso durante particiones parciales de la red.
El coordinador persiste los registros de transacciones en un WAL (Registro de Adelanto) utilizando el consenso de Paxos para durabilidad a través de zonas de disponibilidad. Los proxies de fragmento abstraen los motores de almacenamiento subyacentes—ya sea PostgreSQL, MongoDB o Cassandra—presentando una interfaz unificada para la máquina de ejecución. La detección de conflictos emplea un grafo de dependencias construido durante la fase de secuenciación, permitiendo la ejecución concurrente de transacciones no conflictivas mientras se mantiene la equivalencia a un orden serial.
Un banco de inversión global necesitaba migrar su sistema de liquidación de transacciones de una base de datos monolítica de Oracle a una arquitectura fragmentada que abarcaba las regiones de AWS y Azure. El desafío crítico implicaba garantizar la liquidación atómica de transacciones que involucraban múltiples clases de activos almacenadas en diferentes tecnologías de bases de datos—acciones en PostgreSQL y derivados en ScyllaDB—sin desplegar relojes atómicos o fuentes de tiempo GPS para la sincronización.
Una solución propuesta utilizó transacciones estándar XA con un protocolo de compromiso de dos fases (2PC) gestionado por un gestor de transacciones Narayana. Este enfoque ofreció una fuerte consistencia y un soporte maduro del ecosistema, pero introdujo un comportamiento de bloqueo donde una falla del coordinador durante la fase de preparación dejaría a los fragmentos sosteniendo bloqueos indefinidamente, violando los requisitos de vivacidad durante la inestabilidad de la red entre nubes.
Otra alternativa consideró el patrón Saga implementado a través del Axon Framework, utilizando transacciones compensatorias para escenarios de reversión. Aunque esto proporcionó alta disponibilidad y evitó el bloqueo distribuido, sacrificó la serialización estricta—inaceptable para la liquidación financiera donde los estados intermedios no deben ser observables, y la lógica de compensación para operaciones de mercado externas irreversibles resultó ser prohibitivamente compleja.
La arquitectura seleccionada implementó un coordinador determinista inspirado en Calvin con verificación formal de TLA+. El sistema secuenció todas las transacciones de liquidación a través de una máquina de estado replicada utilizando Raft para el registro de coordinación, luego las ejecutó en el mismo orden a través de todos los fragmentos usando procedimientos almacenados idempotentes. Esto eliminó la necesidad de bloqueo distribuido durante la ejecución y permitió que la verificación del modelo TLA+ probara matemáticamente que el sistema no podía quedar bloqueado ni perder liquidaciones durante particiones arbitrarias de la red.
El despliegue resultó en una reducción del 40% en la latencia de liquidación en comparación con el sistema legado de Oracle, mientras mantenía plenas garantías ACID entre nubes. Durante una posterior interrupción a nivel regional de AWS, el sistema continuó procesando transacciones sin intervención manual, validando las propiedades de vivacidad probadas formalmente.
¿Cuál es la diferencia fundamental entre la serialización estricta y la linealización, y por qué un coordinador de transacciones distribuido generalmente apunta a la primera en lugar de la última?
La serialización estricta combina la serialización (las transacciones parecen ejecutarse en algún orden secuencial) con la restricción de tiempo real de la linealización (las transacciones se completan antes de que comiencen las siguientes). Mientras que la linealización se aplica a operaciones de un solo objeto, la serialización estricta se extiende a transacciones de múltiples objetos. Los candidatos a menudo confunden estas, diseñando sistemas que aseguran la linealización de una sola clave pero no logran prevenir anomalías como el sesgo de escritura entre múltiples claves. Un coordinador logra la serialización estricta estableciendo un orden global de transacciones—generalmente a través de una capa de secuenciación o un oráculo de marcas de tiempo—mientras que la linealización por sí sola puede satisfacerse por fragmento sin garantías de ordenamiento entre fragmentos.
¿Por qué el protocolo de compromiso de dos fases (2PC) se bloquea indefinidamente durante una falla del coordinador, y cómo falla el compromiso de tres fases (3PC) en solucionar esto bajo particiones de red?
En 2PC, una vez que un participante vota "sí" durante la fase de preparación, mantiene bloqueos hasta recibir la decisión global de compromiso/abort del coordinador. Si el coordinador falla después de recibir todos los votos pero antes de transmitir la decisión, los participantes permanecen inciertos y bloqueados, violando la disponibilidad. 3PC intenta resolver esto añadiendo una fase de pre-compromiso y progreso basado en tiempo de espera, pero bajo particiones de red, un participante no puede distinguir entre un coordinador fallido y uno particionado. Esto lleva a escenarios de cerebro dividido donde diferentes particiones toman decisiones conflictivas, violando la consistencia. El problema fundamental es que la imposibilidad de FLP prueba que el consenso determinista es imposible en sistemas asíncronos con incluso un solo proceso defectuoso, lo que significa que cualquier protocolo de compromiso debe elegir entre el bloqueo (seguridad) y la posible inconsistencia (vivacidad) durante ciertos modos de falla.
¿Cómo verifica TLA+ las propiedades de vivacidad en un coordinador de transacciones, y qué operadores lógicos temporales específicos expresan "eventualmente confirma" versus "nunca pierde datos"?
TLA+ utiliza lógica temporal para especificar que las cosas buenas eventualmente ocurren (vivacidad) mientras que las cosas malas nunca ocurren (seguridad). La propiedad de vivacidad de que todas las transacciones iniciadas eventualmente se completan se expresa utilizando el operador eventualmente (◇), típicamente escrito como Iniciada(t) ~> Confirmada(t) (lleva-a), lo que significa que si la transacción t se inicia, eventualmente se confirmará o abortará. Las propiedades de seguridad como "nunca pierde datos" utilizan el operador siempre (□), escrito como □(Confirmada(t) ⇒ ◇(Consulta(t) = Valor)), lo que significa que una vez confirmada, el valor siempre será eventualmente legible. Los candidatos a menudo pasan por alto que la verificación de vivacidad requiere suposiciones de equidad—la equidad débil (WF_vars(Action)) asegura que si una acción permanece habilitada, debe ocurrir eventualmente, evitando la inacción infinita donde el coordinador simplemente deja de tomar pasos. Sin estas restricciones de equidad, los modelos TLA+ satisfacerían trivialmente las propiedades de vivacidad al no hacer nada.