Zum Hauptinhalt springen

Fail Closed, nie destruktiv: Der Zaris-Lizenzlebenszyklus von innen

· 10 Minuten Lesezeit
Clustron Team
Engineering für verteilte Systeme

Der Zaris-Lizenzlebenszyklus

Lizenzierung ist der Teil eines Produkts, über den die meisten Ingenieure nie nachdenken wollen, und man sieht es. Das übliche Muster ist eine Zeitbombe: Ein Datum wird geprüft, und wenn es verstreicht, bestraft die Software Sie — sie wirft beim Start eine Exception, sie beschädigt oder löscht lokalen Zustand, um Sie am „Stehlen" zu hindern, oder sie stürzt schlicht ab und nimmt Ihre Daten mit. Dieses Design behandelt die eigenen Operatoren als Gegner, und es versagt genau in dem Moment, in dem Sie es sich am wenigsten leisten können: in der Produktion, nachdem die Uhr unbemerkt umgesprungen ist.

Zaris nimmt die entgegengesetzte Haltung ein. Die Lizenzprüfung ist der sicherheitskritischste Schalter eines verteilten Datenspeichers und wird entsprechend gebaut: eine einzige reine, deterministische Policy-Funktion, ein sanfter und vollständig umkehrbarer Durchsetzungspfad, der kein einziges Byte zerstört, und eine Uhr pro Maschine, die in dem Moment weiterläuft, in dem Sie einen Schlüssel aktivieren. Dieser Beitrag geht durch, wie dieser Lebenszyklus im ausgelieferten Code tatsächlich funktioniert — denn die interessante Ingenieursarbeit steckt darin, was er Ihnen verweigert anzutun.

Alles oder nichts: Multi-Key-Transaktionen in Zaris

· 10 Minuten Lesezeit
Clustron Team
Engineering für verteilte Systeme

Multi-Key-Transaktionen in Zaris

Ein Begleitbeitrag, Race-Free Coordination on Optimistic CAS, hat dargelegt, dass ein einziges Primitiv — eine vom Store vergebene Version plus ein versionsgeschütztes bedingtes Schreiben — erstaunlich viel Koordination trägt. Er zog auch eine harte Grenze: CAS ist atomar auf einem Key. Bewegen Sie Geld von Konto A auf Konto B, kann ein einzelnes Compare-and-Swap nicht beides abdecken; der ehrliche Rat lautete, die Überweisung als Zustandsmaschine auf einem Key zu modellieren oder zu einer Saga zu greifen.

Diese Grenze ist real, aber sie ist nicht die ganze Geschichte. Zaris hat eine echte Multi-Key-Transaktion — BeginTransactionAsync, ein gestaffeltes Lese-/Schreib-Set, CommitAsync — und sie committet über Keys und über Nodes hinweg mit einer Alles-oder-nichts-Garantie. Dieser Beitrag handelt davon, was diese Transaktion unter der Haube tatsächlich ist (ein clientkoordinierter Two-Phase-Commit über optimistische Versionen), was sie genau garantiert und welche Feinheit darüber entscheidet, ob Ihre Key-übergreifende Invariante tatsächlich hält.

Ein Log, zwei Aufgaben: Wie ein Replikat und ein neuer Owner auf dieselbe Weise aufholen

· 12 Minuten Lesezeit
Clustron Team
Engineering für verteilte Systeme

Aufholen durch Wiedergeben des Logs — ein nach Revision geordnetes Op-Log versorgt Replikate und neue Owner gleichermaßen

Zwei sehr unterschiedlich aussehende Ereignisse in einem verteilten Store sind im Kern dasselbe Problem. Das erste: Ein Replikat fällt hinter seinen Primary zurück — eine GC-Pause, eine langsame Platte, eine kurze Netzwerkpartition — und hält nun eine veraltete Kopie einer Partition, der es irgendwann entsprechen muss. Das zweite: Eine Partition wird einem Node zugewiesen, der sie nie gehalten hat, und dieser Node muss den gesamten Datenbestand vom aktuellen Owner übernehmen. Das eine ist Replikationsverzug; das andere ist Migration. Sie haben unterschiedliche Auslöser, unterschiedliche Betreiber, unterschiedliche Ausfallgeschichten.

Doch die Frage, die beide beantworten müssen, ist identisch: Wie konvergiere ich zur aktuellen Wahrheit dieser Partition, ohne Schreibzugriffe einzufrieren, während ich es tue? Zaris beantwortet beide mit einem einzigen Mechanismus — einem nach Revision geordneten Operations-Log pro Segment, wiedergegeben ab einem bekannten Punkt. Dieser Beitrag handelt von diesem Log: wie es auf dem Schreibpfad aufgebaut wird, wie es begrenzt wird, damit es nicht unbegrenzt wächst, wie es wiedergegeben wird und warum dasselbe Substrat sowohl ein zurückgefallenes Replikat als auch einen brandneuen Owner zur Konvergenz bringt.

Ein Primitiv, viele Garantien: Race-freie Koordination mit optimistischem CAS

· 12 Minuten Lesezeit
Clustron Team
Engineering für verteilte Systeme

Race-freie Koordination mit dem optimistischen CAS von Zaris

Es ist verlockend, einen Datenspeicher an der Länge seiner Befehlsliste zu messen. Redis hat INCR, SETNX, MULTI/EXEC, WATCH, Lua, SCAN, Pub/Sub — für jeden Anlass ein eigenes Verb. Der Zaris-.NET-Client wirkt dagegen fast asketisch. Es gibt kein serverseitiges atomares Increment. Es gibt keine allgemeine Multi-Key-Transaktion, die beliebige Logik ausführt. Es gibt keinen Prefix-Scan. Natives Pub/Sub existiert nur über das RESP-Frontend, nicht im typisierten .NET-Client.

Stattdessen bietet Ihnen der .NET-Client ein kleines, scharfes Koordinationsprimitiv: optimistisches, versioniertes Compare-and-Swap. Dieser Beitrag zeigt, wie weit dieses eine Primitiv tatsächlich trägt — denn die ehrliche Antwort lautet: überraschend weit. Ein Rate Limiter, ein Wallet, das unter tausend gleichzeitigen Abbuchungen nie ins Minus rutscht, eine Job-Queue, in der genau ein Worker jeden Job übernimmt, und ein Feature-Flag-Regelwerk, das bei gleichzeitigen Admin-Änderungen nie ein Update verliert. Alles aus demselben Primitiv, ohne zusätzliche serverseitige Mechanik.

Retries, die Sie nicht schreiben müssen: Ownership-Churn im Zaris-Client überstehen

· 10 Minuten Lesezeit
Clustron Team
Engineering für verteilte Systeme

Transparenter Retry und Reroute bei Ownership-Churn

Hier eine Tatsache über jeden partitionierten Key/Value-Store, die die glänzenden Diagramme gern auslassen: Der Node, der Ihren Schlüssel besitzt, wird wechseln. Ein Node fällt aus, und seine Partitionen gehen per Failover auf ihre Replikate über. Sie skalieren aus, und Partitionen wandern auf das neue Mitglied. Ein bevorzugter Primary kehrt zurück, und der Besitz fällt an ihn zurück. Jedes dieser Ereignisse bedeutet: Der Node, mit dem Ihr Client vor einer Millisekunde noch zufrieden sprach, ist jetzt für einen Teil der Schlüssel der falsche.

Die naive Client-Erfahrung in diesem Moment ist hässlich: ein Verbindungsabbruch, ein generischer „Serverfehler" oder — schlimmer — ein Schreibvorgang, der auf einem Node landet, der nicht mehr der aktive Owner ist, und stillschweigend im Nichts verschwindet. Der Zaris-.NET-Client ist so gebaut, dass nichts davon Ihren Code erreicht. Ein Ownership-Wechsel wird zu einem typisierten Status, der Client routet um zum neuen Owner, und der Retry ist sowohl durch ein Versuchsbudget als auch durch eine Wanduhr-Deadline begrenzt. Im Normalfall dauert Ihr PutAsync einfach ein paar Millisekunden länger und liefert Ok. Dieser Beitrag beschreibt die Mechanik dahinter — und ebenso wichtig: die Fälle, die sie bewusst nicht überdeckt.

Clustron Zaris 2.0.1: Standardmäßig langlebig, Lizenzierung in einer Zeile

· 5 Minuten Lesezeit
Clustron Team
Engineering für verteilte Systeme

Clustron Zaris 2.0.1 — standardmäßig langlebig, Lizenzierung in einer Zeile

Zaris 2.0.1 ist da. Es ist ein Drop-in-Upgrade von 2.0.0 — dasselbe Wire-Protokoll, dieselbe Client-API, dieselben On-Disk- und In-Memory-Formate — und es bietet zwei Gründe zum Upgrade: Es macht den Ownership- und Recovery-Pfad des Clusters bei Ausfällen spürbar langlebiger, und es gibt Zaris ein sauberes, integriertes Trial-und-Lizenz-Modell, mit dem Sie es reibungslos evaluieren und produktiv betreiben können.

Kein bestätigter Schreibvorgang bleibt zurück: Das Ownership- und Recovery-Fundament unter 12 Stunden Chaos

· 10 Minuten Lesezeit
Clustron Team
Engineering für verteilte Systeme

Kein Verlust bestätigter Schreibvorgänge, belegt über 12 Stunden Chaos

Der Happy Path eines verteilten Key/Value-Stores lässt sich leicht richtig umsetzen. Ein Schreibvorgang landet auf dem Primary, wird an die Replikate gestreamt, alle sind sich einig, weiter geht's. Wäre das die ganze Geschichte, wäre Langlebigkeit ein gelöstes Problem, und dieser Beitrag würde nicht existieren.

Die schweren Probleme liegen in den Nahtstellen — den kurzen, unbequemen Momenten, in denen sich der Cluster mitten in einem Übergang befindet. Ein Node startet mitten in einer Partitionsmigration neu. Ein Replikat fällt weit hinter den Active zurück, von dem es kopiert, und dann geht dieser Active per Failover an jemand anderen. Der Besitz einer Partition wechselt auf einen neuen Node, während noch Schreibvorgänge zum alten unterwegs sind. Jedes davon ist ein Fenster: eine Spanne von wenigen Sekunden, in der ein bestätigter Schreibvorgang — einer, dem der Client als erfolgreich gemeldet wurde — stillschweigend verschwinden kann, wenn die Übergabe nicht exakt stimmt. Nicht weil die Storage-Engine fehlerhaft wäre, sondern weil zwei Teile des Systems für einen Moment uneins darüber waren, wer die Wahrheit besitzt.

In diesem Beitrag geht es darum, wie Zaris diese Fenster schließt — und, worauf es wirklich ankommt, wie wir uns davon überzeugt haben, dass es funktioniert: indem wir den Cluster zwölf Stunden am Stück unter kontinuierlichem, gezieltem Chaos betrieben haben.

Allokationsfreie Hot Paths: Wie der Zaris-.NET-Client ValueTask nutzt

· 6 Minuten Lesezeit
Clustron Team
Engineering für verteilte Systeme

Der Zaris-.NET-Client nutzt ValueTask in seinen Hot-Path-Operationen

Meistens ist Task<T> genau der richtige Rückgabetyp für eine asynchrone Methode, und man sollte nicht zweimal darüber nachdenken. Es gibt aber einen bestimmten Ort, an dem er unbemerkt Kosten verursacht: ein Hot Path, der synchron abschließt und millionenfach aufgerufen wird.

Der Mechanismus: Task<T> ist ein Referenztyp. Jeder Aufruf, der einen zurückgibt, allokiert ein Task-Objekt auf dem Heap — selbst wenn die Operation synchron abschließt. Ein Cache-Treffer direkt aus einem lokalen Puffer, ein Awaitable, das bereits fertig ist: Nichts davon erfordert echte Asynchronität, dennoch zahlen Sie für ein Heap-Objekt, das das Ergebnis trägt. Eine Allokation ist nichts. Bei der Aufrufrate eines Clients mit hohem Durchsatz — einer engen Schleife mit Millionen kleiner Gets und Puts — ist das ein stetiger Strom kleiner Heap-Allokationen, und dieser Strom füttert den Garbage Collector. Mehr Gen-0-Collections, mehr CPU für GC statt für Ihre Arbeit, mehr Jitter bei den Tail-Latenzen.

Der Zaris-.NET-Client setzt genau dort an, wo es zählt, und nirgendwo sonst. Dieser Beitrag handelt von dieser Entscheidung: welche Methoden sich geändert haben, warum, welche Regeln Sie für den korrekten Einsatz befolgen müssen und — bewusst — welche Methoden wir unangetastet gelassen haben.

Große Werte, kleine Pausen: Large-Object-Chunking in Zaris

· 6 Minuten Lesezeit
Clustron Team
Engineering für verteilte Systeme

Large-Object-Chunking hält große Werte vom LOH fern

Es gibt eine Zahl, die sich jeder .NET-Performance-Ingenieur irgendwann merkt: 85.000 Bytes. Jede einzelne Allokation ab etwa dieser Größe landet nicht auf dem normalen Heap für kleine Objekte, sondern auf dem Large Object Heap (LOH). Der LOH ist ein anderes Tier. Er wird nur bei einer Gen-2-(vollständigen) Garbage Collection eingesammelt und standardmäßig nicht kompaktiert. Diese Kombination ist in Ordnung für einen großen Puffer, den man einmal allokiert und behält. Sie ist nicht in Ordnung für einen latenzarmen In-Memory-Store, der wiederholt große Werte schreibt und überschreibt.

Stellen Sie sich die Last vor: große serialisierte Blobs, umfangreiche JSON-Dokumente, Bilder, Protokoll-Payloads — gespeichert, aktualisiert, ersetzt, immer wieder. Jeder dieser großen Schreibvorgänge legt ein frisches Objekt auf dem LOH ab. Da der LOH nicht kompaktiert wird, verschmelzen freigegebene Bereiche nicht zu zusammenhängendem Speicher, sondern fragmentieren. Und weil jede Rückgewinnung eine vollständige Gen-2-Collection bedeutet, werden die Pausen länger und treten häufiger auf, genau dann, wenn der Working Set wächst. Für einen Store, dessen ganzes Versprechen niedrige Latenz ist, ist das die falsche Art von Überraschung.

Zaris liefert ein optionales Feature, das den LOH für solche Werte komplett umgeht. Es ist standardmäßig aus, und dieser Beitrag erklärt, was es tut, wie es funktioniert und — ebenso wichtig — wann Sie es einschalten sollten und wann nicht.

Elastische Skalierung: Zaris-Server ohne Downtime hinzufügen und entfernen

· 5 Minuten Lesezeit
Clustron Team
Engineering für verteilte Systeme

Einen Zaris-Store live unter einem Supervisor vergrößern und verkleinern

Die Kapazität stimmt nie lange. Der Traffic wächst, ein Launch steht an, eine Saison endet — und der Store, den Sie im letzten Quartal dimensioniert haben, ist entweder überlastet oder halb leer. Ob das eine lästige Pflicht oder eine Krise ist, entscheidet eine einfache Frage: Können Sie die Größe eines laufenden Stores ändern, ohne ihn herunterzufahren?

Bei Zaris lautet die Antwort ja, mit einer wichtigen Asymmetrie, die man gleich zu Beginn ehrlich benennen sollte. Das Hochskalieren — das Hinzufügen von Servern — ist die einfache, sichere, verlustfreie Richtung und geschieht live, während der Store weiter bedient. Das Herunterskalieren — das Entfernen von Servern — wird ebenfalls unterstützt, ist aber ein bewusster, überwachter Vorgang, weil die Daten eines ausscheidenden Servers zuerst irgendwohin müssen.

Dieser Beitrag behandelt beide Richtungen: einen Store mit Add-ZrServer vergrößern, ihn mit Remove-ZrServer verkleinern, warum das Herunterskalieren einen Drain braucht und welche Rolle die Web-Konsole spielt.