Zum Hauptinhalt springen

42 Posts getaggt mit "Clustron"

Artikel rund um den verteilten Key-Value-Store Clustron.

Alle Tags anzeigen

Die Worker-Pool-Obergrenze: Wenn ein Node bei 25 % CPU ein Plateau erreicht

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

Ein Node bei nahezu 25 % CPU mit flachem Durchsatz, weil der Dispatch-Worker-Pool die Obergrenze war

Hier ist ein Benchmark-Ergebnis, das wie ein Widerspruch aussieht. Ein Zaris-Node, der eine leselastige Workload bedient, erreicht seine Obergrenze bei knapp unter einer halben Million Ops/s und weigert sich zu steigen — fügen Sie mehr Client-Verbindungen und mehr Lastgeneratoren hinzu, die Zahl bewegt sich nicht. Die naheliegende Diagnose lautet „er ist gesättigt." Nur sagt das CPU-Diagramm etwas anderes: Der Node steht bei etwa einem Viertel seiner verfügbaren CPU. Drei von vier Kernen sind untätig, und der Durchsatz ist flach.

Das ist kein CPU-limitierter Node und — wenn Sie das sorgfältig ausgeschlossen haben — auch kein Client-limitierter Benchmark. Es ist eine dritte Sache, und zwar ein Klassiker: Der Worker-Pool für das Request-Dispatching war schmaler, als die Arbeit es wollte, sodass Requests in der Warteschlange standen, während Kerne Däumchen drehten.

Drop-in-Cache für ASP.NET Core: IDistributedCache und HybridCache auf Zaris

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

Drop-in-verteilter-Cache für ASP.NET Core auf Zaris

Die meisten Gründe, in einer .NET-App zu einem verteilten Cache zu greifen, nennen den Cache gar nicht beim Namen. Sie aktivieren Output Caching, und es verlangt ein IDistributedCache. Sie aktivieren Sessions, und die Middleware will einen Backing-Store. Sie schalten das Teilen von Data-Protection-Schlüsseln über Instanzen hinweg ein, und wieder braucht es einen Ort für Bytes, den jeder Node sieht. Der Anwendungscode ist gegen eine Abstraktion geschrieben; offen ist nur, welche Implementierung Sie beim Start registrieren.

Zaris beantwortet diese Frage mit drei kleinen NuGet-Paketen, die jeweils eine bestimmte ASP.NET-Core-Nahtstelle bedienen: ein schlichtes IDistributedCache, ein zweistufiges HybridCache und ein Session-Store. Sie registrieren beim Start eine Zeile, und der Rest Ihrer App — einschließlich Drittanbieter-Bibliotheken, die nur die Abstraktion kennen — cacht auf einem Zaris-Cluster, ohne dass sich der Code ändert, der den Cache nutzt. Dieser Beitrag geht alle drei durch und ist dabei bewusst klar darüber, wo jedes ehrlicherweise endet.

Anatomie eines Failovers: Was mit einem laufenden Schreibvorgang geschieht, wenn der Owner stirbt

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

Anatomie eines Failovers in Zaris

Ein Failover ist der Moment, in dem ein verteilter Store am ehrlichsten zeigt, was er wirklich ist. Im Normalbetrieb sehen alle Stores gleich aus: Ein Schreibvorgang landet auf einem Owner, wird bestätigt, weiter geht's. Das Design zeigt sich erst, wenn der Owner mitten im Satz verschwindet — ein Node hält die aktive Kopie einer Ihrer Partitionen, Schreibvorgänge landen gerade auf ihm, und dann ist er weg. Hart beendet. Netzwerkpartitioniert. OOM. Der Cluster hat ein paar Sekunden, um das zu bemerken, sich auf einen neuen Owner zu einigen und den Verkehr wieder fließen zu lassen — und ob er das korrekt tut, entscheidet darüber, ob Ihr bestätigter Schreibvorgang überlebt oder stillschweigend verdunstet.

Dieser Beitrag folgt dieser Abfolge von Anfang bis Ende, in der Reihenfolge, in der Zaris sie tatsächlich ausführt, und benennt die Fälle, in denen die Antwort wirklich „der Schreibvorgang ist verloren" lautet — denn ein Failover-Beitrag, der nur den Happy Path beschreibt, ist nicht lesenswert.

Welches Primitiv für welches Problem: Ein Feldführer durch das Zaris-Datenmodell

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

Das richtige Zaris-Primitiv für das Problem wählen

Der Großteil dieses Blogs ist jeweils tief in ein einzelnes Thema eingestiegen — Compare-and-Swap, Multi-Key-Transaktionen, native Datenstrukturen, Streams, Watch, das darunterliegende Op-Log. Jeder Beitrag beantwortet „wie funktioniert dies". Dieser beantwortet eine andere, praktischere Frage: Wonach greifen Sie, wenn ein Problem vor Ihnen liegt?

Diese Frage ist wichtig, weil die falsche Wahl selten ein Absturz ist. Es ist ein System, das in der Demo funktioniert und dann unter Last ein Update verliert, tausend Schreiber durch einen Schlüssel schleust oder eine Fire-and-Forget-Benachrichtigung nutzt, wo ein dauerhaftes Log nötig war. Die Primitive hindern Sie nicht daran, sie falsch zu benutzen. Dies ist also ein Feldführer: das mentale Modell, das sie verbindet, eine Entscheidungstabelle, ein Gang durch jeden Zweig mit ehrlicher Eignung und ehrlicher Grenze und am Ende ein Flussdiagramm.

Die Steuerungsebene in Ihrer Shell: Einen Zaris-Cluster mit PowerShell betreiben

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

Einen Zaris-Cluster mit PowerShell bereitstellen und betreiben

Das meiste, was man über einen Datenspeicher liest, handelt vom Datenpfad — Lese- und Schreibvorgänge, das Wire-Protokoll, wie schnell es ist. Doch bevor das alles zählt, muss jemand das Ding aufsetzen: entscheiden, wie viele Partitionen es hat, wie viele Kopien jeder davon, wo die Ports liegen, es starten, bestätigen, dass es gesund hochgekommen ist, und es im Betrieb beobachten. Das ist die Steuerungsebene, und in Zaris lebt sie in PowerShell.

Dies ist eine Day-one-Anleitung für Operatoren. Wir legen einen Workspace an, stellen einen Store bereit, starten ihn und lesen dann seinen Live-Zustand zurück — alles aus dem Modul AdminShell. Keine Web-Konsole nötig, nichts von Hand bearbeitet. Und weil bei einer Operator-Geschichte Vertrauen der ganze Punkt ist, benennen wir klar die Entscheidungen, die New-ZrStore Ihnen vorlegt, und was jede tatsächlich kostet.

Derselbe Code, mit oder ohne Netzwerk: Der Embedded-Modus von Zaris

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

Zaris Embedded-In-Process-Modus

Die meisten verteilten Datenspeicher zwingen Sie, sich früh und endgültig zwischen zwei Welten zu entscheiden. Da ist der „echte" Store — ein Cluster, den Sie deployen, auf den Sie einen Client über das Netzwerk richten und mit dem Sie über ein Wire-Protokoll sprechen. Und da ist der „falsche" Store, zu dem Sie in Unit-Tests greifen: ein In-Memory-Dictionary, ein Mock, ein handgeschriebener Stub, der gerade genug der Schnittstelle implementiert, damit der Test kompiliert. Beide haben nichts gemeinsam. Ihr Test prüft das Verhalten des Stubs, nicht das des Stores, und die Lücke dazwischen ist genau der Ort, an dem sich Bugs verstecken.

Zaris hebt diese Entscheidung auf. Derselbe typisierte .NET-Client, der über TLS mit einem verteilten Cluster spricht, betreibt den Store auch eingebettet in Ihrem Prozess, ohne Socket, ohne Partition-Map und ohne Deployment — und zwar mit derselben Store-Engine, nicht mit einem Ersatz. Welchen von beiden Sie bekommen, wählen Sie mit einer einzigen Connection-String. Dieser Beitrag erklärt, wie das funktioniert, wofür es sich wirklich eignet und wo die harte Grenze verläuft, an der der Embedded-Modus endet und ein Cluster beginnt.

Die eigenen Schreibvorgänge lesen: Das Zaris-Konsistenzmodell, ehrlich dargestellt

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

Die eigenen Schreibvorgänge lesen — ein Owner pro Partition

Es gibt eine Frage, die jeder Entwickler irgendwann an einen verteilten Store richtet, meist direkt nach einem verwirrenden Bug-Report: Wenn ich einen Wert schreibe und ihn sofort zurücklese, sehe ich dann garantiert, was ich geschrieben habe? Das klingt, als müsste es eine Ein-Wort-Antwort geben. Gibt es nicht — nicht für irgendeinen partitionierten, replizierten Store, und nicht für Zaris. Die ehrliche Antwort lautet „ja, innerhalb einer Partition, weil Lesevorgänge zum selben einzelnen Owner gehen wie Ihr Schreibvorgang" — und das Interessante ist alles, was in dieser Einschränkung steckt.

Dieser Beitrag ist das Konsistenzmodell von Zaris an einem Ort zusammengetragen. Über die Einzelteile haben wir separat geschrieben — optimistisches Compare-and-Swap, transparenter Retry bei Ownership-Churn, das wiederabspielbare Op-Log, das Replikate speist, Multi-Key-Transaktionen. Hier verbinden wir sie aus Sicht des Lesers und beantworten die einzige Frage, die an der Tastatur zählt: Was wird mir beim Lesen tatsächlich zugesichert? Einschließlich, und vor allem, wo die Zusicherung endet.

Keyspace-Benachrichtigungen, die ein Failover überstehen

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

Redis-Keyspace-Benachrichtigungen auf dem replizierten nativen Watch von Zaris

Keyspace-Benachrichtigungen sind eines der nützlichsten Features von Redis und eines der unauffällig fragilsten. Die Idee ist wunderbar: Jedes Mal, wenn ein Schlüssel geschrieben, gelöscht oder ablaufend ist, veröffentlicht der Server ein Event auf einem wohlbekannten Pub/Sub-Kanal, und jeder Interessierte kann per PSUBSCRIBE reagieren — einen Cache invalidieren, einen Worker wecken, eine Projektion aktualisieren. Kein Polling, kein GET in einer Schleife, das fragt „hat es sich schon geändert?".

Die Fragilität steckt im Kleingedruckten. Redis-Keyspace-Benachrichtigungen sind Fire-and-Forget-Pub/Sub, ausgesendet von dem Node, der den Befehl verarbeitet hat, an Subscriber, die mit genau diesem Node verbunden sind. In einem geclusterten Deployment heißt das: Ein Subscriber hört nur von Schreibvorgängen, die zufällig auf dem Node landeten, an den er angebunden ist, und fällt dieser Node per Failover aus, geht die Subscription — und der Event-Strom, den sie trug — mit. Das Feature funktioniert auf einer einzelnen Box wunderbar und wird schnell subtil, sobald es mehr als eine gibt.

Zaris spricht exakt dasselbe Protokoll — CONFIG SET notify-keyspace-events, die Kanäle __keyspace@0__ und __keyevent@0__, ein gewöhnliches PSUBSCRIBE von jedem Redis-Client in jeder Sprache. Die Mechanik darunter ist jedoch keine Neuimplementierung des Redis-Notifiers. Es ist eine dünne Brücke auf ein Feature, das Zaris bereits hatte: einen nativen, clusterweiten, replizierten Watch. Das ändert, was die Benachrichtigungen wert sind.

Kein Auth-Server: Offline verifizierbare Tokens, Rollen und Scopes in Zaris

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

Offline verifizierbare Tokens, Rollen und Scopes in Zaris

Die meisten Wege, einem verteilten Datenspeicher eine Authentifizierung vorzuschalten, enden damit, ein zweites verteiltes System zu seinem Betrieb hinzuzufügen: einen Auth-Dienst, den man aufrufen muss, eine Session-Datenbank, die repliziert werden muss, einen Token-Introspection-Endpunkt, den jeder Node auf dem Hot Path erreichen muss. Sie haben den Store gesichert und sich eine neue Verfügbarkeitsabhängigkeit und eine neue Latenzquelle eingekauft.

Zaris geht einen anderen Weg, und zwar einen bewusst langweiligen: ein Signaturschlüssel pro Cluster und Tokens, die jeder Node selbst verifizieren kann. Ein Token ist ein JWT, signiert mit dem privaten Schlüssel des Clusters; jeder Manager und jeder Node hält die öffentliche Hälfte und prüft die Signatur offline — kein Aufruf an einen Auth-Server, kein Quorum, kein Datenbank-Lookup. Security ist standardmäßig aus, und ein Cluster mit ausgeschalteter Security verhält sich exakt wie ein ungesicherter. Dieser Beitrag handelt davon, was sich einschaltet, wenn Sie sie aktivieren: die Form des Tokens, das Rollen-und-Scope-Modell, die beiden Ebenen, auf denen die Durchsetzung tatsächlich stattfindet, und — weil das Gegenteil vorzutäuschen der Weg zu einem falschen Sicherheitsgefühl ist — die betrieblichen Grenzen, die man leicht falsch macht.

Replikationsfaktor ist keine Ausfallsicherheit: Einen Zaris-Cluster auf Kubernetes für Dauerhaftigkeit dimensionieren

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

Einen Zaris-Cluster auf Kubernetes für Dauerhaftigkeit dimensionieren

Beim Deployment eines replizierten Stores auf Kubernetes liegt ein verlockender Gedankengang nahe: Ich habe replicationFactor: 2 gesetzt, also hat jede Partition ein Backup, also überstehe ich den Verlust eines Nodes. Das fühlt sich wasserdicht an. Für eine überraschend häufige Clustergröße ist es dennoch falsch — und zwar auf die stille Art, die erst auffällt, wenn tatsächlich zum ersten Mal ein Pod stirbt.

Zaris auf Kubernetes speichert Daten im Arbeitsspeicher und macht sie durch Replikation, nicht durch Festplatte dauerhaft: Das Node-Datenvolume ist ein emptyDir, und ein neu eingeplanter Pod baut sich aus der Kopie auf einem anderen Pod wieder auf. Dieses Design ist solide — verlässt sich aber vollständig darauf, dass es tatsächlich eine Kopie auf einem anderen Pod gibt. Ob diese Kopie existiert, entscheidet nicht replicationFactor allein. Es entscheidet die Arithmetik zwischen Pod-Anzahl und Replikationsfaktor, und wenn Sie diese Arithmetik falsch ansetzen, läuft der Store einwandfrei, bedient jeden Lese- und Schreibzugriff und hält stillschweigend eine Partition, die nirgendwohin replizieren kann.