Saltar al contenido principal

Muchas claves, pocos viajes de ida y vuelta: cómo Zaris hace fan-out de una operación masiva

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

Haciendo fan-out de una operación masiva a sus nodos propietarios

Pídele a un almacén distribuido una clave y el costo lo domina un solo número: el viaje de ida y vuelta al nodo que la posee. La búsqueda en sí es nanosegundos; la red es microsegundos. Ahora pide mil claves. Si iteras y llamas a Get mil veces, pagas ese viaje de ida y vuelta mil veces, en serie, y el almacén gasta casi todo el tiempo de reloj sentado ocioso esperando paquetes. Las claves podrían estar repartidas sobre cuatro nodos que podrían haber respondido en paralelo —pero un bucle ingenuo nunca les da la oportunidad.

Zaris tiene tres APIs masivas —GetManyAsync, PutManyAsync, DeleteManyAsync— y un ExecuteBatchAsync mixto por debajo de ellas, y toda su razón de existir es convertir "mil claves" en "una solicitud por nodo propietario, emitidas en paralelo". Este artículo es la ruta de fan-out de principio a fin: cómo el cliente agrupa claves por propietario, por qué las cuatro APIs colapsan sobre un único motor, cómo un campo Index mantiene las respuestas en orden a través de dos capas de concurrencia, y por qué —a diferencia de una transacción multiclave— una operación masiva es por ítem y el éxito parcial es normal.

Un salto al propietario: cómo el cliente de Zaris enruta una clave

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

Cómo el cliente de Zaris enruta una clave a su propietario

Hay dos formas honestas de construir un cliente de caché distribuida. La primera es elegir cualquier nodo, enviarle la solicitud, y dejar que el clúster la reenvíe internamente a quien posea la clave —simple en el cliente, pero cada solicitud que aterriza en el nodo equivocado paga un salto de red adicional dentro del clúster. La segunda es hacer al cliente lo bastante listo como para saber qué nodo posee la clave antes de enviar nada, para que el primer socket que toque sea el que realmente puede responder. Zaris toma la segunda vía. Un GET sale de tu proceso ya dirigido al nodo que sostiene la clave —sin proxy, sin salto de reenvío, sin coordinador en el medio.

Este artículo es la vista interna de cómo funciona eso: la función que convierte una clave en un propietario, la tabla de búsqueda que el cliente mantiene en memoria, y —la parte que es fácil de equivocar— cómo el cliente se mantiene correcto cuando la propiedad se mueve mientras tu tráfico está en vuelo.

Un propietario que reinicia no tiene derecho a su propia vacuidad

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

Reconstruir un propietario reiniciado a partir de sus réplicas

Un failover cubre el momento en que un propietario muere: el clúster elige un superviviente y sigue sirviendo. Una migración planificada cubre mover la partición de un propietario sano a propósito. Este artículo trata del tercer acto, el que corre después de que las sirenas se apagan —el proceso propietario original reinicia, se reúne al clúster, y quiere su partición de vuelta. Su almacén de nada-en-disco, todo-en-memoria volvió vacío. Los datos de los que es responsable siguen vivos, pero están vivos en las réplicas que siguieron sirviendo mientras estaba caído.

Todo el problema de corrección está contenido en una frase: al propietario reiniciado no se le puede permitir confiar en su propia vacuidad. Un almacén vacío se ve exactamente como un almacén que alguien limpió deliberadamente. Si el nodo asume "soy el propietario y no tengo datos, por lo tanto esta partición está vacía", servirá alegremente NotFound para millones de claves vivas y, peor, dejará que su estado vacío fluya de vuelta a las réplicas y las elimine. Este artículo recorre las cinco políticas pequeñas y puras que Zaris usa para asegurar que eso nunca ocurra.

Cómo se forma un clúster de Zaris: membresía, el mapa y la disponibilidad condicionada a la convergencia

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

Cómo se forma un clúster de Zaris: membresía, el mapa y la disponibilidad condicionada a la convergencia

La mayor parte de lo que se escribe sobre almacenes distribuidos trata del estado estable —lecturas, escrituras, replicación— o de los fallos dramáticos: un failover cuando muere un propietario, un cut-over cuando se mueve una partición. Pero hay un momento más silencioso que decide si algo de eso funciona: el momento en que el clúster se forma. Antes de poder enrutar una sola clave, los nodos tienen que ponerse de acuerdo sobre quién está en el clúster, quién posee qué porción del espacio de claves y —el paso que la mayoría de los sistemas resuelven mal— si es seguro empezar a servir siquiera.

Este artículo sigue esa secuencia de arranque en el orden en que Zaris realmente la ejecuta: membresía, el mapa de particiones y las compuertas de disponibilidad que se interponen entre "el proceso está en marcha" y "el nodo está aceptando tráfico". También traza una línea, con honestidad, entre lo que Zaris implementa por sí mismo y lo que hereda del runtime de clúster subyacente sobre el que está construido.

Dos clústeres, un change feed: replicar a través de una WAN sin estirar Zaris

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

Dos clústeres independientes enlazados por un change feed reanudable a través de una WAN

Tarde o temprano alguien hace la pregunta: tenemos un clúster en una región y usuarios en otra —¿no podemos simplemente añadir unos cuantos nodos allá y dejar que un clúster abarque ambas? Es un instinto razonable. Un clúster, un namespace, una cadena de conexión, datos en todas partes. El instinto también es una trampa, y vale la pena ser preciso sobre por qué.

Un clúster de Zaris está diseñado para una red de datacenter. La membresía se rastrea con heartbeats en temporizadores cortos. La propiedad de una partición se mueve entre nodos mediante un handshake que asume que el otro lado responde rápido. El failover aísla a un propietario sospechoso de estar muerto y promueve una réplica en cuestión de segundos. Cada uno de esos mecanismos está calibrado para un enlace donde el viaje de ida y vuelta se mide en microsegundos y un nodo "lento" está genuinamente enfermo —no meramente a ochenta milisegundos y un océano de distancia. Pon la mitad de los nodos al otro lado de una WAN y no habrás construido un clúster geo-distribuido; habrás construido un clúster que ahora confunde la latencia normal de WAN con un fallo, flapea la propiedad y arriesga split-brain la primera vez que el enlace entre regiones tiene un hipo.

Así que la forma correcta no es un clúster estirado. Son dos clústeres independientes —cada uno autocontenido, cada uno con su propia propiedad y failover quedándose enteramente en su propia LAN— unidos por un change feed asíncrono y reanudable. Este artículo trata sobre ese patrón: por qué la independencia es la decisión portante, y cómo el log de operaciones de Zaris ya te entrega lo único que un replicador de WAN realmente necesita —un cursor desde el cual reanudar.

El piso de latencia: un microsegundo de trabajo dentro de diez de plomería

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

Un microsegundo de trabajo dentro de diez microsegundos de plomería

Aquí hay un número que reencuadra cómo piensas sobre un almacén clave/valor. Cuando aislamos el almacén en memoria de Zaris y le damos operaciones sin nada más en el camino —sin socket, sin serialización, sin enrutamiento— un solo hilo sirve lecturas a más de un millón por segundo, y escala limpiamente a más de ocho millones a lo largo de ocho hilos. El almacén, en otras palabras, hace el trabajo real de un GET en menos de dos microsegundos, y enfáticamente no es el cuello de botella.

Y sin embargo un GET completo sobre una conexión TCP real, en la misma máquina, se estanca en unos pocos cientos de miles por segundo. El almacén puede hacer el trabajo cinco veces más rápido de lo que el servidor puede entregarlo. Así que la pregunta de rendimiento interesante sobre Zaris no es "¿qué tan rápido es el almacén?". Es lo contrario: ¿a dónde va todo el tiempo entre el socket y el almacén? Este artículo es la respuesta, trazada operación por operación, porque la brecha entre 1,7 microsegundos de lógica y 10 a 13 microsegundos de CPU de servidor por operación no es ruido —es el piso de latencia, y casi todo él es plomería.

Migrar una partición con cero pérdida de datos: el protocolo de cut-over

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

El protocolo de cut-over de particiones de Zaris

Un failover es lo que ocurre cuando un propietario muere —el clúster tiene segundos para elegir a un superviviente y el mapa de particiones nunca se mueve. La migración es la prima más tranquila y más peligrosa: el propietario está perfectamente sano, y quieres mover una partición fuera de él a propósito —para hacer crecer el clúster, para rebalancear, para drenar un nodo que estás a punto de retirar. Nada ha fallado, que es exactamente por qué el listón está más alto. A un failover se le permiten unas pocas escrituras de cola honestamente perdidas en el peor caso; a una migración planificada no. Si mover una partición del nodo A al nodo B puede perder una sola escritura confirmada, la migración no es una característica, es un pasivo.

Este artículo recorre el protocolo de cut-over que Zaris realmente ejecuta, en orden, y dedica la mayor parte de su tiempo al único paso que todos resuelven mal: el momento en que la fuente finalmente queda "libre" para descartar su copia. Ese paso es un arma cargada, y la ingeniería interesante es el seguro que lleva.

Escanear un espacio de claves que no se queda quieto: cómo SCAN itera un clúster

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

Muchos segmentos ordenados fusionados en un único stream paginado y ordenado

Un GET de clave única es fácil de razonar: haz hash de la clave, encuentra su propietario, pregunta a ese único nodo. SCAN es el tipo de operación opuesto. No tiene clave —hace una pregunta sobre todo el espacio de claves: dame cada clave en este rango, una página a la vez. Y en un almacén particionado y replicado ese espacio de claves no es una sola cosa en un solo lugar. Está dividido en 256 segmentos repartidos sobre cuantos nodos ejecutes, cada nodo sosteniendo solo las porciones que posee actualmente, y todo el conjunto se está escribiendo mientras iteras. No hay índice ordenado global que recorrer. Entonces, ¿de dónde viene el orden, a qué apunta exactamente un token de reanudación, y qué le pasa a tu escaneo cuando una clave se escribe —o una partición se mueve— a mitad de camino?

Este artículo sigue un SCAN a través de las tres capas que realmente lo sirven: un solo segmento, un solo nodo, y el cliente que cose los nodos entre sí. Cada capa resuelve una pieza del problema, y los límites honestos de la operación caen de cómo esas piezas encajan.

El techo de memoria: por qué un nodo de Zaris nunca crece sin límite

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

Un nodo de Zaris manteniendo el uso de memoria en una banda tranquila por debajo de su techo, expulsando al 80% hasta el 70% para que las escrituras nunca crucen el límite

Aquí hay una pregunta que suena simple y no lo es: ¿qué ocurre cuando un almacén en memoria se queda sin memoria?

La respuesta ingenua es "se cae" —el proceso trepa hasta que el sistema operativo lo mata. La respuesta un poco menos ingenua es "rechaza escrituras". Zaris no hace ninguna de las dos por defecto. Un nodo de Zaris es un almacén en memoria, pero deliberadamente no es uno ilimitado: cada nodo es un buffer acotado con un techo duro, y cuando los datos que posee se acercan a ese techo el nodo expulsa sus datos más fríos para hacer espacio. Las escrituras siguen teniendo éxito; el límite se sostiene; el proceso no se hincha. El nodo se comporta como una caché, porque por debajo, lo es.

Lo que cruza el cable: la anatomía de un registro de Zaris

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

La anatomía de un registro almacenado de Zaris

La mayor parte de lo que Zaris hace bien —replicar una escritura a un backup, poner al día a una réplica rezagada, traspasar una partición a un nuevo propietario— se reduce a una pregunta silenciosa: ¿cuál es, exactamente, la unidad de datos que se mueve entre nodos? Si esa unidad está bien, la convergencia es casi aburrida. Si deja caer un campo o lleva el equivocado, obtienes una clave eliminada resucitada, una réplica que no puede distinguir lo obsoleto de lo fresco, o la contabilidad de un nodo filtrándose en otro.

En Zaris esa unidad es un solo tipo —StoredRecord— y vale la pena desmontarlo campo por campo, porque cada decisión en él es portante. Este artículo es la anatomía: qué contiene el registro, cómo se enmarca en el cable, por qué una eliminación viaja como un registro en lugar de como una ausencia, por qué hay dos números de versión distintos, y —igual de importante— qué deliberadamente se deja atrás en cada nodo y nunca cruza el cable en absoluto.