Tema: distributed-systems
-
Trazado distribuido en líneas generales: spans, identificadores de padre y W3C Trace Context
Una traza es un árbol de spans, cada uno con un identificador de traza, un identificador de span propio, un identificador de span padre, marcas de tiempo, atributos y un estado; la cabecera W3C traceparent transporta el identificador de traza, el identificador del padre y un indicador sampled entre límites de proceso, y un servicio que se limita a reenviar ambas cabeceras mantiene igualmente unida la traza.
-
Qué garantiza un clúster Raft: mayorías, un solo líder y lecturas linealizables
Los sistemas de consenso como etcd (Raft) permiten que una mayoría de servidores acuerde un registro ordenado; permanecen correctos ante cualquier número de fallos, pero solo avanzan mientras una mayoría sea alcanzable. Las lecturas linealizables pasan por el consenso y cuestan latencia; las lecturas serializables se sirven localmente y pueden estar desactualizadas.
-
Diseñar operaciones idempotentes y reintentos seguros
Una operación es idempotente cuando ejecutarla varias veces tiene el mismo efecto que ejecutarla una sola vez; el RFC 9110 establece esto para los métodos HTTP, y una cabecera Idempotency-Key traslada la propiedad a POST. Guardar la clave junto con una huella y el resultado, informar los conflictos con 409 y 422, y eliminar las claves tras un plazo documentado.
-
Sagas: flujos de trabajo de varios pasos entre servicios con compensación en lugar de rollback
Una saga es una secuencia de transacciones locales en distintos servicios, cada una desencadenando la siguiente; si un paso falla, los pasos anteriores se deshacen mediante transacciones de compensación que escribe quien desarrolla. Las sagas restauran la consistencia sin transacciones distribuidas, pero renuncian al aislamiento, de modo que los estados intermedios son visibles y las compensaciones deben diseñarse, no darse por supuestas.
-
Amplificación de la latencia de cola: cuando una solicitud espera a la más lenta de cien
Una solicitud que se ramifica hacia N backends es tan lenta como la respuesta más lenta, de modo que una respuesta lenta de 1 en 100 por backend hace que alrededor del 63 % de las solicitudes con cien ramas sean lentas. El p99 de la hoja se convierte en la mediana de la raíz; los remedios son menos hojas, solicitudes hedged o tied tras un retraso percentil, plazos con resultados parciales, y eliminar las causas de las colas en las hojas.
-
Publicar eventos de forma fiable con un outbox transaccional
Escribir el evento en una tabla outbox dentro de la misma transacción de base de datos que el cambio de estado, y dejar que un relay independiente lo publique en el broker. Esto elimina la ventana en la que el estado se guarda pero el evento se pierde (o al revés), al precio de una entrega al menos una vez y de un relay que operar.
-
Los compartimentos estancos por dependencia mantienen disponibles los endpoints no relacionados cuando una dependencia se atasca
Hipótesis: cuando un servicio llama a varias dependencias desde un único grupo compartido de hilos o de espacios de concurrencia, una dependencia que se vuelve lenta (no que cae) arrastra consigo a los endpoints no relacionados en cuanto el grupo se agota; dar a cada dependencia su propio grupo acotado mantiene a los demás endpoints cerca de su latencia y tasa de error habituales durante el mismo atasco.
-
Réplicas de lectura y lag de replicación: cómo se ven las lecturas obsoletas y cómo acotarlas
Una réplica por streaming aplica el registro del primario con cierto retraso, por lo que una lectura justo después de una escritura puede no verla. Las lecturas se enrutan según cuánta obsolescencia tolere cada solicitante, los modos de replicación síncrona se usan solo donde su latencia es aceptable, y hay que entender que reproducir el registro puede cancelar consultas largas en la réplica.
-
Fundamentos de gRPC: contratos protobuf, streaming y dónde encaja
gRPC llama a métodos definidos en un archivo .proto, con Protocol Buffers como lenguaje de definición de interfaz y formato de transmisión; ofrece llamadas unarias y por streaming, deadlines, metadatos y un conjunto fijo de códigos de estado sobre HTTP/2. Encaja bien en comunicación entre servicios y en backends móviles; los navegadores necesitan gRPC-Web, y quienes integran públicamente suelen esperar JSON sobre HTTP.
-
Hashing consistente: ubicación estable de claves cuando los nodos aparecen y desaparecen
Aplicar hash a una clave módulo el número de nodos reasigna la mayoría de las claves cada vez que se añade o elimina un nodo. El hashing consistente coloca nodos y claves en un anillo de modo que solo se mueven las claves adyacentes al nodo modificado; los nodos virtuales equilibran la carga, y las variantes basadas en tablas, como Maglev, sacrifican algo de estabilidad de ubicación a cambio de una búsqueda más rápida.
-
Trazado distribuido a grandes rasgos: spans, ID de padre y propagación del contexto de traza W3C
Una traza es un árbol de spans, cada uno con un ID de traza, su propio ID de span, un ID de span padre, marcas de tiempo, atributos y un estado; la cabecera traceparent de W3C lleva el ID de traza, el ID de padre y un indicador sampled a través de los límites de proceso, y un servicio que se limita a reenviar ambas cabeceras mantiene las trazas intactas.
-
CAP y PACELC como ayudas para decidir, no como eslóganes
CAP prohíbe solo una esquina del espacio de diseño: disponibilidad perfecta y consistencia linealizable mientras dura una partición de red. PACELC añade el compromiso cotidiano entre latencia y consistencia cuando no hay partición. Usados como preguntas y no como etiquetas, ambos ayudan a decidir, operación por operación, dónde un sistema puede devolver datos obsoletos y dónde debe coordinarse.
-
Backpressure y colas acotadas: que la etapa más lenta marque el ritmo
Una cola sin límite convierte la sobrecarga en agotamiento de memoria y latencia ilimitada. El backpressure consiste en que el consumidor indique al productor cuánto puede aceptar, desde la demanda en Reactive Streams hasta un write() de Node.js que devuelve false; una cola acotada y un comportamiento definido cuando se llena son el mínimo que necesita cada etapa de un servicio.
-
¿Qué señal de sobrecarga debería usar un servicio pequeño para descartar carga: tiempo de espera en cola, solicitudes en curso o CPU?
Pregunta abierta: las guías citan la CPU, la latencia, la longitud de la cola y el número de hilos como posibles disparadores para descartar carga, y dejan la elección a cada servicio. Para un servicio con pocas instancias y sin sistema global de cuotas, ¿qué señal, umbral y regla de prioridad han mantenido realmente los equipos en producción y cómo los ajustaron?
-
Bloqueos distribuidos y leases de líder: expiración, fencing tokens y lo que un bloqueo no puede garantizar
Un bloqueo distribuido es un lease que expira: un proceso detenido por el recolector de basura, por contención de CPU o por un retraso de red puede seguir actuando cuando su lease ya pasó a otro cliente. Solo un fencing token monótonamente creciente, verificado por el recurso protegido, hace que el bloqueo sea seguro para la corrección; si se usa solo para evitar trabajo duplicado, basta con menos.
-
Relojes lógicos: marcas de tiempo de Lamport, relojes vectoriales y relojes híbridos
Los relojes de pared de máquinas distintas no coinciden, así que ordenar eventos por marca de tiempo hace perder actualizaciones. Las marcas de Lamport dan un orden coherente con la causalidad, los relojes vectoriales además detectan actualizaciones concurrentes y los relojes lógicos híbridos mantienen un valor cercano a la hora real sin perder el orden causal.
-
Circuit breakers: fallar rápido cuando una dependencia está caída o lenta
Un circuit breaker cuenta los fallos y las llamadas lentas a una dependencia; al superar un umbral se abre y rechaza las llamadas de inmediato, y luego deja pasar unas pocas llamadas de prueba (semiabierto) antes de volver a cerrarse. Protege los hilos del llamador y da margen a la dependencia para recuperarse, pero solo funciona con ventanas razonables, un fallback y un timeout por debajo.
-
Entrega como máximo una vez, al menos una vez y exactamente una vez
Un sistema de mensajería puede entregar un mensaje como máximo una vez (puede perderlo), al menos una vez (puede duplicarlo) o, en la práctica, exactamente una vez (el consumidor deduplica). Lo habitual es combinar entrega al menos una vez con consumidores idempotentes; "exactamente una vez" es una propiedad de todo el pipeline, no del broker.
-
Pipelines de eliminación de datos entre servicios, almacenes derivados y copias de seguridad
Modela la eliminación de los datos de una persona como un trabajo con un estado por cada almacén del mapa de datos: difunde un evento, exige que cada servicio responsable informe de su finalización con recuentos, trata de forma explícita el almacenamiento de objetos con versiones y los almacenes derivados, limita el tiempo de retención en las copias de seguridad o destruye claves por titular, y mantiene una lista de supresión para repetir la eliminación tras una restauración.
Legible por máquina: JSON