Saltar al contenido principal

Fallar cerrado, nunca destructivo: por dentro del ciclo de vida de licencias de Zaris

· 11 min de lectura
Clustron Team
Ingeniería de Sistemas Distribuidos

El ciclo de vida de licencias de Zaris

El licenciamiento es la parte de un producto en la que la mayoría de los ingenieros nunca quieren pensar, y se nota. El patrón habitual es una bomba de tiempo: se comprueba una fecha, y cuando pasa, el software te castiga — lanza una excepción al arrancar, corrompe o borra el estado local para evitar que lo "robes", o simplemente revienta y se lleva tu data con él. Ese diseño trata a tus propios operadores como adversarios, y falla justo en el momento en que menos te lo puedes permitir: en producción, después de que el reloj girara silenciosamente.

Zaris adopta la postura opuesta. La comprobación de licencia es el interruptor más crítico para la seguridad de un almacén de datos distribuido, así que está construida como tal: una única función de política pura y determinista, un camino de aplicación elegante y totalmente reversible que nunca destruye un byte, y un reloj por máquina que se reanuda en el instante en que activas una clave. Este post recorre cómo funciona realmente ese ciclo de vida en el código que se envía — porque la ingeniería interesante aquí está en lo que se niega a hacerte.

Un log, dos trabajos: cómo una réplica y un nuevo propietario se ponen al día de la misma forma

· 13 min de lectura
Clustron Team
Ingeniería de Sistemas Distribuidos

Ponerse al día reproduciendo el log — un único op-log ordenado por revisión alimenta por igual a réplicas y nuevos propietarios

Dos eventos de aspecto muy diferente en un almacén distribuido resultan ser el mismo problema por debajo. El primero: una réplica se queda atrás de su primario — una pausa de GC, un disco lento, una breve partición de red — y ahora sostiene una copia obsoleta de una partición que debe eventualmente igualar. El segundo: una partición se reasigna a un nodo que nunca la ha tenido, y ese nodo debe adquirir el conjunto de datos entero del propietario actual. Uno es lag de replicación; el otro es migración. Tienen disparadores diferentes, operadores diferentes, historias de fallo diferentes.

Pero la pregunta que cada uno tiene que responder es idéntica: ¿cómo converjo a la verdad actual de esta partición sin congelar las escrituras mientras lo hago? Zaris responde a ambos con un único mecanismo — un log de operaciones ordenado por revisión mantenido por segmento, reproducido desde un punto conocido. Este post trata de ese log: cómo se construye en el camino de escritura, cómo se acota para que no pueda crecer sin límite, cómo se reproduce, y por qué el exacto mismo sustrato lleva tanto a una réplica rezagada como a un propietario completamente nuevo a la convergencia.

Todo o nada: transacciones multiclave en Zaris

· 10 min de lectura
Clustron Team
Ingeniería de Sistemas Distribuidos

Transacciones multiclave en Zaris

Un post complementario, Coordinación sin carreras sobre CAS optimista, argumentaba que una única primitiva — una versión propiedad del almacén más una escritura condicional guardada por versión — lleva una cantidad notable de coordinación. También trazó una línea dura: el CAS es atómico sobre una clave. Mueve dinero de la cuenta A a la cuenta B y un único compare-and-swap no puede cubrir ambas; el consejo honesto fue modelar la transferencia como una máquina de estados sobre una clave, o recurrir a una saga.

Esa línea es real, pero no es toda la historia. Zaris tiene una genuina transacción multiclave — BeginTransactionAsync, un conjunto de lectura/escritura preparado, CommitAsync — y hace commit a través de claves y a través de nodos con una garantía de todo-o-nada. Este post trata de lo que esa transacción realmente es por debajo (un commit de dos fases coordinado por el cliente sobre versiones optimistas), de lo que garantiza exactamente, y de la única sutileza que decide si tu invariante entre claves realmente se mantiene.

Una primitiva, muchas garantías: coordinación libre de condiciones de carrera con CAS optimista

· 13 min de lectura
Clustron Team
Ingeniería de Sistemas Distribuidos

Coordinación libre de condiciones de carrera con CAS optimista en Zaris

Es tentador juzgar un almacén de datos por la longitud de su lista de comandos. Redis tiene INCR, SETNX, MULTI/EXEC, WATCH, Lua, SCAN, pub/sub: un verbo para cada ocasión. El cliente .NET de Zaris, en cambio, parece casi austero. No hay incremento atómico del lado del servidor. No hay una transacción general multiclave que ejecute lógica arbitraria. No hay escaneo por prefijo. El pub/sub nativo existe únicamente a través del front-end RESP, no del cliente .NET tipado.

Lo que el cliente .NET te da en su lugar es una primitiva de coordinación pequeña y afilada: compare-and-swap optimista versionado. Esta publicación trata de hasta dónde llega realmente esa única primitiva, porque la respuesta honesta es: sorprendentemente lejos. Un limitador de tasa, una cartera que nunca queda en negativo bajo mil débitos concurrentes, una cola de trabajos donde exactamente un worker reclama cada trabajo, y un conjunto de reglas de feature flags que nunca pierde una actualización bajo ediciones concurrentes de administradores. Todos ellos, a partir de la misma primitiva, sin maquinaria adicional del lado del servidor.

Reintentos que no escribes: sobrevivir a la rotación de propiedad en el cliente de Zaris

· 11 min de lectura
Clustron Team
Ingeniería de Sistemas Distribuidos

Reintento y reencaminamiento transparentes bajo rotación de propiedad

Aquí hay un hecho sobre cualquier almacén clave-valor particionado que los diagramas pulidos tienden a omitir: el nodo que posee tu clave se moverá. Un nodo falla y sus particiones conmutan por error a sus réplicas. Escalas horizontalmente y las particiones migran al nuevo miembro. Un primario preferido vuelve y la propiedad conmuta de vuelta a él. Cada uno de esos eventos significa que el nodo con el que tu cliente hablaba felizmente hace un milisegundo es, en este momento, el nodo equivocado para algún conjunto de claves.

La experiencia ingenua del cliente en ese momento es fea: un reinicio de conexión, un genérico "error de servidor" o —peor— una escritura que aterriza en un nodo que ya no es el dueño activo y silenciosamente no va a ninguna parte. El cliente .NET de Zaris está construido para que nada de eso llegue a tu código. Un cambio de propiedad se convierte en un estado tipado, el cliente reencamina al nuevo dueño, y el reintento está acotado tanto por un presupuesto de intentos como por una fecha límite de reloj de pared. En el caso común, tu PutAsync simplemente tarda unos milisegundos más y devuelve Ok. Esta publicación trata de la maquinaria que hace que eso sea cierto y —no menos importante— de los casos que deliberadamente no disimula.

Ninguna escritura confirmada se queda atrás: la columna vertebral de propiedad y recuperación bajo 12 horas de caos

· 11 min de lectura
Clustron Team
Ingeniería de Sistemas Distribuidos

Cero pérdida de escrituras confirmadas, demostrado tras 12 horas de caos

El camino feliz de un almacén clave-valor distribuido es fácil de acertar. Una escritura llega al primario, se transmite a las réplicas, todos están de acuerdo y sigues adelante. Si esa fuera toda la historia, la durabilidad sería un problema resuelto y esta entrada no existiría.

Los problemas difíciles viven en las costuras: los momentos breves e incómodos en los que el clúster está en plena transición. Un nodo se reinicia en medio de una migración de partición. Una réplica se queda muy rezagada respecto al activo del que está copiando, y entonces ese activo conmuta por error hacia otro. La propiedad de una partición se mueve a un nodo nuevo mientras aún hay escrituras en vuelo hacia el antiguo. Cada una de ellas es una ventana: un lapso de unos segundos en el que, si el traspaso no es exactamente correcto, una escritura confirmada —una que se le dijo al cliente que había tenido éxito— puede desaparecer silenciosamente. No porque el motor de almacenamiento tenga errores, sino porque dos partes del sistema discreparon, por un instante, sobre quién era dueño de la verdad.

Esta entrada trata sobre cómo Zaris cierra esas ventanas y —la parte que realmente importa— cómo nos convencimos de que funciona, ejecutando el clúster bajo caos continuo y deliberado durante doce horas seguidas.

Clustron Zaris 2.0.1: durable por defecto, licenciado en una línea

· 5 min de lectura
Clustron Team
Ingeniería de Sistemas Distribuidos

Clustron Zaris 2.0.1 — durable por defecto, licenciado en una línea

Zaris 2.0.1 ya está disponible. Es una actualización directa desde 2.0.0 —mismo protocolo de cable, misma API de cliente, mismos formatos en disco y en memoria— y hace dos cosas que valen la pena actualizar: hace que el camino de propiedad y recuperación del clúster sea significativamente más durable bajo fallos, y le da a Zaris un modelo de prueba y licencia integrado y limpio para que puedas evaluarlo y ejecutarlo en producción sin fricción.

Rutas calientes sin asignaciones: cómo el cliente .NET de Zaris usa ValueTask

· 7 min de lectura
Clustron Team
Ingeniería de Sistemas Distribuidos

El cliente .NET de Zaris usa ValueTask en sus operaciones de ruta caliente

La mayor parte del tiempo, Task<T> es exactamente el tipo de retorno correcto para un método asíncrono, y no deberías pensártelo dos veces. Pero hay un lugar específico donde te cuesta en silencio: una ruta caliente que se completa de forma síncrona, llamada millones de veces.

Aquí está el mecanismo. Task<T> es un tipo de referencia. Cada llamada que devuelve uno asigna un objeto Task en el heap — incluso cuando la operación se completa de forma síncrona. Un hit de caché servido directamente desde un búfer local, un awaitable que ya está completado: nada de eso requiere asincronía real, pero aún pagas por un objeto en el heap para transportar el resultado. Una asignación no es nada. A la tasa de llamadas de un cliente de alto rendimiento — un bucle apretado haciendo millones de pequeños Gets y Puts — eso es un flujo constante de pequeñas asignaciones en el heap, y ese flujo alimenta al recolector de basura. Más recolecciones de gen-0, más CPU gastada en GC en lugar de tu trabajo, más jitter en tus latencias de cola.

El cliente .NET de Zaris ataca esto exactamente donde importa y en ningún otro sitio. Este post trata de esa decisión: qué métodos cambiaron, por qué, las reglas que tienes que seguir para usarlos correctamente, y — deliberadamente — qué métodos dejamos intactos.

Valores grandes, pausas pequeñas: fragmentación de objetos grandes en Zaris

· 7 min de lectura
Clustron Team
Ingeniería de Sistemas Distribuidos

La fragmentación de objetos grandes mantiene los valores grandes fuera del LOH

Hay un número que todo ingeniero de rendimiento de .NET acaba memorizando: 85.000 bytes. Cualquier asignación individual en o por encima de aproximadamente ese tamaño no va al heap normal de objetos pequeños — va al Large Object Heap (LOH). El LOH es un animal diferente. Solo se recolecta durante una recolección de basura de gen-2 (completa), y por defecto no se compacta. Esa combinación está bien para un búfer grande que asignas una vez y conservas. No está bien para un almacén en memoria de baja latencia que escribe y sobrescribe repetidamente valores grandes.

Imagina la carga de trabajo: blobs serializados grandes, documentos JSON grandes, imágenes, payloads de protocolo — almacenados, actualizados, reemplazados, una y otra vez. Cada una de esas escrituras grandes deposita un objeto nuevo en el LOH. Como el LOH no se compacta, los huecos liberados no se fusionan de vuelta en espacio contiguo; se fragmentan. Y como recuperar algo de él implica una recolección completa de gen-2, las pausas se alargan y aterrizan con más frecuencia justo a medida que crece el working set. Para un almacén cuyo argumento entero es baja latencia, esa es la clase equivocada de sorpresa.

Zaris incluye una función opcional para esquivar el LOH por completo para estos valores. Está desactivada por defecto, y este post trata de lo que hace, cómo funciona, y — igual de importante — cuándo deberías y cuándo no deberías activarla.

Escalado elástico: añadir y quitar servidores de Zaris sin tiempo de inactividad

· 6 min de lectura
Clustron Team
Ingeniería de Sistemas Distribuidos

Crecer y reducir un almacén Zaris en vivo bajo un supervisor

La capacidad nunca es la adecuada por mucho tiempo. El tráfico crece, llega un lanzamiento, termina una temporada — y el almacén que dimensionaste el trimestre pasado está o bien al límite o bien medio ocioso. La pregunta que decide si eso es una tarea o una crisis es simple: ¿puedes cambiar el tamaño de un almacén en marcha sin tumbarlo?

Para Zaris la respuesta es sí, con una asimetría importante que vale la pena reconocer de entrada. Escalar hacia afuera — añadir servidores — es la dirección fácil, segura y sin pérdidas, y ocurre en vivo mientras el almacén sigue sirviendo. Escalar hacia adentro — quitar servidores — también está soportado, pero es una operación deliberada y monitorizada porque la data del servidor que se va tiene que ir a algún sitio primero.

Este post recorre ambas direcciones: hacer crecer un almacén con Add-ZrServer, reducirlo con Remove-ZrServer, por qué la reducción necesita un drain, y dónde encaja la consola web.