Zaris 2.0.0: Native Datenstrukturen, Streams und ein Redis-Protokoll-Frontend
Heute veröffentlichen wir Zaris 2.0.0 — das größte Release seit der allgemeinen Verfügbarkeit von Zaris und das erste mit einem Major-Versionssprung. Es macht aus Zaris, einem schnellen, replizierten Key/Value-Store, einen vollwertigen Datenstruktur-Server: native Hashes, Listen, Sets, Sorted Sets, Pub/Sub und Redis Streams, alle auf dieselbe Weise partitioniert und repliziert wie Ihre Keys bereits.
Und es öffnet die Tür für alle anderen. Jeder Node kann nun ein Redis-Protokoll-Frontend (RESP) bereitstellen, sodass eine Anwendung in Python, Ruby, Java, Go — jeder Sprache mit einem Redis-Client — auf Zaris zeigen und es als Drop-in nutzen kann, ohne natives SDK und ohne eine Zeile umzuschreiben.
Die Versionsnummer ist eine 2 und keine 1.x, und das hat einen Grund: 2.0.0 ändert das Wire-Protokoll. Lesen Sie den Upgrade-Hinweis unten, bevor Sie es ausrollen.
Native Datenstrukturen
Zaris 1.x speicherte Werte. Zaris 2.0.0 speichert Collections. Hashes, Listen, Sets und Sorted Sets sind nun erstklassige, serverseitige Typen mit echten, typisierten .NET-APIs:
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);
Jede Collection ist ein einzelner logischer Wert, der auf der Partition liegt, die ihren Key besitzt, und jede Mutation läuft über denselben replizierten Pfad wie ein gewöhnliches Put — ein Whole-Value-Compare-and-Swap-Read-Modify-Write —, sodass ein Hash oder ein Sorted Set genauso dauerhaft und hochverfügbar ist wie ein einfacher Key. Wir haben sie gegen .NET-, Java- und Ruby-Clients gebaut und validiert, damit die Semantik sprachübergreifend gilt und nicht nur In-Process.
Die vollständige API finden Sie im Leitfaden zu Datenstrukturen.
Pub/Sub und Streams
Zwei weitere Collection-Arten runden das Set ab.
Pub/Sub bietet clusterweites Publish/Subscribe — eine Nachricht wird an jeden Subscriber im gesamten Cluster verteilt, nicht nur an die, die mit einem Node verbunden sind.
Streams sind das eigentliche Highlight: ein Append-only-Log mit Consumer Groups und blockierenden Lesezugriffen, nativ in Zaris und erreichbar über die RESP-Befehle XADD / XREAD / XREADGROUP. Damit ist Zaris eine fünfte Art von Collection — ein dauerhaftes, repliziertes Ereignis-Log, das Sie für Work Queues, Change Feeds und Event Sourcing nutzen können, live validiert gegen einen Standard-StackExchange.Redis-Client über einen 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);
Details finden Sie in den Leitfäden zu Streams und Pub/Sub.
Ein Redis-Protokoll-Frontend für jede Sprache
Zaris sprach mit erstklassigen Clients schon immer sein eigenes effizientes binäres Protokoll — dem .NET-Client, PowerShell, der Konsole. 2.0.0 fügt einen zweiten Zugang hinzu: Jeder Node kann zusätzlich einen RESP2-Listener betreiben, sodass jeder bestehende Redis-Client direkt mit Zaris sprechen kann.
Es funktioniert wie bei Redis Cluster. Zaris hasht Keys mit derselben CRC16(key) % 16384-Slot-Berechnung wie Redis Cluster, und jeder Node bietet eine korrekte CLUSTER SLOTS-Sicht an, sodass ein Cluster-fähiger Redis-Client jeden Key direkt zum Node routet, der ihn besitzt — kein Proxy, kein zusätzlicher Hop. Erreicht der Befehl den Besitzer, wird er direkt aus dem In-Process-Store dieses Nodes bedient, und bei einem Failover erhält der Client ein MOVED und aktualisiert seine Slot-Map. Sie möchten keinen Cluster-fähigen Client betreiben? Stellen Sie die Nodes hinter einen Load Balancer oder nutzen Sie Sentinel, dann akzeptiert jeder Node jeden Key.
# 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
Wir haben die Abdeckung gegen StackExchange.Redis 2.8.16 gemessen: 126 Befehle unterstützt, 92 sauber nicht unterstützt und null Fehlschläge. „Sauber nicht unterstützt“ ist der wichtige Teil — Befehle, die Zaris nicht implementiert (Lua/EVAL, Geo, HyperLogLog, Bitmaps, Key-übergreifendes *STORE, blockierende List-Pops, RDB/AOF-Persistenz), werden ehrlich abgelehnt, statt stillschweigend das Falsche zu tun. Was vorhanden ist, deckt den Alltag ab: Strings, INCR/DECR, MGET/MSET, Hashes, Listen, Sets, Sorted Sets, Streams, SUBSCRIBE/PUBLISH, Keyspace-Benachrichtigungen, MULTI/EXEC/WATCH (abgebildet auf die nativen Two-Phase-Commit-Transaktionen von Zaris) und das Muster für verteilte Locks mit SET NX PX. Es ist RESP2, legen Sie Ihre Client-Versionen also fest.
Es gibt einen ganzen Beitrag dazu, wie dieses Frontend funktioniert — Jede Sprache, ein Store — sowie die genaue Befehlskompatibilitätsmatrix, falls Sie einen bestimmten Befehl prüfen möchten, bevor Sie umsteigen.
Lesezugriffe, die mit Ihren Cores skalieren
Zaris routet jeden Key zu einem Besitzer und verteilt die Arbeit pro Core, statt alles durch eine einzelne Event-Loop zu leiten. Die praktische Wirkung: Der Lese-Durchsatz steigt mit jedem hinzugefügten Core. Über das RESP-Frontend läuft GET mit etwa 483.000 Ops/Sek. auf einem Core und rund 946.000 auf vier, während Single-Thread-Engines wie Redis und Memurai bei etwa 740.000–780.000 flach bleiben, egal wie viele Cores Sie ihnen geben.
Wir sind ehrlich — das ist etwa der doppelte Durchsatz für die vierfachen Cores, nicht perfekt linear. Aber die Richtung ist der springende Punkt: Eine partitionierte, multithreaded Engine hat Luft nach oben, eine Engine mit einer einzelnen Event-Loop nicht. Die vollständige Aufschlüsselung, mit den ehrlichen Vorbehalten zu Client-gebundenem Benchmarking, finden Sie unter Lesezugriffe, die mit Ihren Cores skalieren.
2.0.0 strafft auch den Rest des Hot Path: Der SET-Pfad verlor ein redundantes Read-before-Write, die Kernoperationen des nativen Clients (Get/Put/Delete/Expire/Persist/TTL) geben nun ValueTask zurück, sodass synchrone Abschlüsse nichts allozieren, und ein optionaler Large-Object-Modus speichert große, häufig aktualisierte Werte als Chunks unterhalb der LOH-Schwelle, um den GC-Druck zu senken.
Upgrade: Dies ist ein Wire-Bruch
2.0.0 ist eine Major-Version, weil sie das Protokoll ändert. Das native Cluster-Routing wurde auf CRC16-ausgerichtetes Hashing umgestellt, und das Protokoll-Minimum ist nun 2 — ein 2.0.0-Server weist Clients vor 2.0 (1.x) beim HELLO-Handshake ab. Das ist Absicht: Ein 1.x-Client und ein 2.0.0-Server wären sich uneinig darüber, wo ein Key liegt, daher scheitern wir schnell beim Verbindungsaufbau, statt die Platzierung zu beschädigen.
Die Upgrade-Regel ist einfach: Stellen Sie Clients und Server gemeinsam auf 2.0.0 um. Richten Sie stattdessen einen Redis-Client auf das RESP-Frontend, umgehen Sie die Versionskopplung des nativen Clients vollständig — der RESP-Zugang spricht ein stabiles, standardisiertes Protokoll.
Erste Schritte
NuGet:
dotnet add package Clustron.Zaris.SDK --version 2.0.0
Windows: Laden Sie clustron-zaris-2.0.0-win-x64.zip von der Release-Seite herunter (Prüfung anhand von 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
Sie nutzen bereits Redis und fragen sich, wie ein Umstieg praktisch aussieht? Beginnen Sie mit Von Redis kommend oder dem Installationsleitfaden, wenn Sie einfach einen Cluster zum Laufen bringen möchten.
Zaris bleibt unter der Business Source License 1.1 kostenlos im Betrieb, kommerzieller Support ist unter clustron.io/support erhältlich. Vollständige Release Notes und Downloads finden Sie auf GitHub. Wir freuen uns darauf zu hören, was Sie damit bauen.