Saltar al contenido principal

Zaris 2.0.0: estructuras de datos nativas, Streams y un front-end del protocolo de Redis

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

Zaris 2.0.0 — Estructuras de datos nativas, Streams y un front-end del protocolo de Redis

Hoy lanzamos Zaris 2.0.0, la mayor versión desde que Zaris alcanzó la disponibilidad general, y la primera con un salto de versión mayor. Convierte a Zaris de un almacén clave/valor rápido y replicado en un servidor completo de estructuras de datos: hashes, listas, conjuntos, conjuntos ordenados, pub/sub y Redis Streams nativos, todos particionados y replicados de la misma forma que ya lo están tus claves.

Y abre la puerta a todos los demás. Cada nodo ahora puede exponer un front-end del protocolo de Redis (RESP), de modo que una aplicación en Python, Ruby, Java, Go —cualquier lenguaje con un cliente de Redis— puede apuntar a Zaris y usarlo como reemplazo directo, sin un SDK nativo y sin reescribir una línea.

El número de versión es un 2, no un 1.x, por una razón: la 2.0.0 cambia el protocolo de cable. Lee la nota de actualización de más abajo antes de implementarlo.

Dos formas de entrar, un solo almacén, siete tipos de datos

Estructuras de datos nativas​

Zaris 1.x almacenaba valores. Zaris 2.0.0 almacena colecciones. Los hashes, listas, conjuntos y conjuntos ordenados son ahora tipos de primera clase, del lado del servidor, con APIs de .NET reales y tipadas:

await client.DataStructures.Hash("user:42").SetAsync("email", "ada@example.com");
await client.DataStructures.SortedSet("leaderboard").AddAsync("ada", score: 4096);
var top = await client.DataStructures.SortedSet("leaderboard").RangeByRankAsync(0, 9);

Cada colección es un único valor lógico que vive en la partición propietaria de su clave, y cada mutación pasa por la misma ruta replicada que un Put ordinario —una lectura-modificación-escritura de valor completo con compare-and-swap— de modo que un hash o un conjunto ordenado es exactamente tan duradero y de alta disponibilidad como una clave simple. Las construimos y validamos frente a clientes de .NET, Java y Ruby para que la semántica se mantenga entre lenguajes, no solo en proceso.

Consulta la guía de estructuras de datos para ver la API completa.

Pub/Sub y Streams​

Otros dos tipos de colección completan el conjunto.

Pub/Sub te ofrece publicación/suscripción en todo el clúster: difunde un mensaje a todos los suscriptores del clúster, no solo a los conectados a un nodo.

Streams son el verdadero titular: un registro de solo anexado con grupos de consumidores y lecturas bloqueantes, nativo de Zaris y accesible a través de los comandos RESP XADD / XREAD / XREADGROUP. Eso hace de Zaris un quinto tipo de colección: un registro de eventos duradero y replicado que puedes usar para colas de trabajo, feeds de cambios y event sourcing, validado en vivo frente a un cliente estándar de StackExchange.Redis sobre un socket.

await client.Streams.Stream("orders").AppendAsync(new { id = 1001, total = 59.90 });
var batch = await client.Streams.Stream("orders").ReadGroupAsync("fulfilment", "worker-1", count: 10);

Los detalles están en las guías de streams y pub/sub.

Un front-end del protocolo de Redis para cualquier lenguaje​

Zaris siempre ha hablado su propio protocolo binario eficiente a los clientes de primera clase: el cliente de .NET, PowerShell, la consola. La 2.0.0 añade una segunda puerta: cada nodo también puede ejecutar un listener RESP2, de modo que cualquier cliente de Redis existente puede hablar con Zaris directamente.

Funciona de la forma en que lo hace Redis Cluster. Zaris aplica el hash a las claves con el mismo cálculo de slot CRC16(key) % 16384 que usa Redis Cluster, y cada nodo anuncia una vista precisa de CLUSTER SLOTS, de modo que un cliente de Redis consciente del clúster enruta cada clave directamente al nodo que la posee: sin proxy, sin salto adicional. Cuando el comando alcanza al propietario se sirve directamente desde el almacén en proceso de ese nodo, y en una conmutación por error el cliente recibe un MOVED y actualiza su mapa de slots. ¿Prefieres no ejecutar un cliente consciente del clúster? Pon los nodos detrás de un balanceador de carga o usa Sentinel en su lugar, y cualquier nodo aceptará cualquier clave.

# point any Redis client at a Zaris node's RESP port
redis-cli -h zaris-0 -p 6379 SET greeting "hello from zaris"
redis-cli -h zaris-0 -p 6379 GET greeting

Medimos la cobertura frente a StackExchange.Redis 2.8.16: 126 comandos soportados, 92 no soportados limpiamente y cero fallos. "No soportado limpiamente" es la parte importante: los comandos que Zaris no implementa (Lua/EVAL, geo, HyperLogLog, bitmaps, *STORE entre claves, pops de listas bloqueantes, persistencia RDB/AOF) se rechazan honestamente en lugar de hacer silenciosamente lo incorrecto. Lo que sí está ahí cubre el día a día: cadenas, INCR/DECR, MGET/MSET, hashes, listas, conjuntos, conjuntos ordenados, streams, SUBSCRIBE/PUBLISH, notificaciones de espacio de claves, MULTI/EXEC/WATCH (asignados a las transacciones nativas de confirmación en dos fases de Zaris) y el patrón de bloqueo distribuido SET NX PX. Es RESP2, así que fija las versiones de tu cliente.

Hay un artículo completo sobre cómo funciona este front-end —Cualquier lenguaje, un solo almacén— y la matriz exacta de compatibilidad de comandos si quieres comprobar un comando específico antes de cambiar.

Lecturas que escalan con tus núcleos​

Zaris enruta cada clave a un propietario y despacha el trabajo por núcleo, en lugar de canalizarlo todo a través de un solo bucle de eventos. El efecto práctico: el rendimiento de lectura sube a medida que añades núcleos. A través del front-end RESP, GET se ejecuta a aproximadamente 483.000 ops/s en un núcleo y alrededor de 946.000 en cuatro, mientras que los motores monohilo como Redis y Memurai se mantienen planos cerca de 740.000–780.000 sin importar cuántos núcleos les des.

Seamos honestos: eso es alrededor de 2× el rendimiento por 4× los núcleos, no perfectamente lineal. Pero la dirección es lo que importa: un motor particionado y multihilo tiene adónde crecer, y un motor de un solo bucle de eventos no. El desglose completo, con las advertencias honestas sobre el benchmarking limitado por el cliente, está en Lecturas que escalan con tus núcleos.

La 2.0.0 también ajusta el resto de la ruta caliente: la ruta de SET perdió una lectura-antes-de-escribir redundante, las operaciones centrales del cliente nativo (Get/Put/Delete/Expire/Persist/TTL) ahora devuelven ValueTask para que las finalizaciones síncronas no asignen nada, y un modo opcional de objetos grandes almacena los valores grandes y frecuentemente actualizados como fragmentos sub-LOH para aliviar la presión del GC.

Actualización: esto es una ruptura del protocolo de cable​

La 2.0.0 es una versión mayor porque cambia el protocolo. El enrutamiento nativo del clúster pasó a un hashing alineado con CRC16, y el mínimo del protocolo es ahora 2: un servidor 2.0.0 rechaza a los clientes anteriores a 2.0 (1.x) en el handshake HELLO. Eso es deliberado: un cliente 1.x y un servidor 2.0.0 estarían en desacuerdo sobre dónde vive una clave, así que fallamos rápido en el momento de la conexión en lugar de corromper la colocación.

La regla de actualización es simple: mueve clientes y servidores a 2.0.0 juntos. Si en su lugar apuntas un cliente de Redis al front-end RESP, evitas por completo el acoplamiento de versiones del cliente nativo: la puerta RESP habla un protocolo estable y estándar.

Primeros pasos​

NuGet:

dotnet add package Clustron.Zaris.SDK --version 2.0.0

Windows: descarga clustron-zaris-2.0.0-win-x64.zip desde la página de la versión (verifícalo con SHA256SUMS.txt).

Docker:

docker pull clustron/zaris-node:2.0.0
docker pull clustron/zaris-manager:2.0.0

Kubernetes (Helm):

helm install zaris oci://registry-1.docker.io/clustron/zaris --version 2.0.0 \
-n zaris --create-namespace

¿Ya estás en Redis y te preguntas cómo es un cambio en la práctica? Empieza con Si vienes de Redis, o con la guía de instalación si solo quieres un clúster en marcha.

Zaris sigue siendo de ejecución gratuita bajo la Business Source License 1.1, con soporte comercial disponible en clustron.io/support. Las notas completas de la versión y las descargas están en GitHub. Nos encantaría saber qué construyes con él.