Microsoft Researchs neue Remote-Cache-Store-Technologie „Garnet“
(github.com/microsoft)- Garnet ist ein von Microsoft Research entwickelter Remote-Cache-Store, der auf dem RESP-Wire-Protokoll basiert, sodass bestehende Redis-Clients ohne Änderungen verwendet werden können
- Bei vielen Client-Verbindungen und kleinen Batches bietet es eine höhere Durchsatzrate und Skalierbarkeit als vergleichbare Open-Source-Cache-Stores; auf Azure-VMs liegt die Latenz im 99,9. Perzentil bei aktiviertem Accelerated Networking oft unter 300 Mikrosekunden
- Es basiert auf modernem .NET, läuft unter Linux und Windows, unterstützt benutzerdefinierte Operationen, Stored Procedures und Module in C# und bietet zudem Unterstützung für Lua-Skripte
- Die Speicher-Engine Tsavorite unterstützt tiered Storage über Speicher, SSD und Cloud-Storage, nicht blockierende Checkpoints, Recovery, einen Operations-Log für Persistenz, Multi-Key-Transaktionen sowie Sharding, Replikation und dynamische Key-Migration im Cluster-Modus
- Als neue Funktionen wurden Vector Sets Preview und Range Index Preview hinzugefügt; ein Garnet-Paper soll in der VLDB 2026 erscheinen
Garnet als Remote-Cache-Store
- Garnet ist ein neuer Remote-Cache-Store von Microsoft Research
- Als Ausgangspunkt wurde das RESP-Wire-Protokoll gewählt, sodass vorhandene Redis-Clients in verschiedenen Programmiersprachen ohne Änderungen genutzt werden können
- Als Beispiel kann in C# StackExchange.Redis verwendet werden
- Bei vielen Client-Verbindungen und kleinen Batches liefert es bessere Durchsatzrate und Skalierbarkeit als vergleichbare Open-Source-Cache-Stores, was bei großen Apps und Services zu Kostensenkungen führen kann
- Auf typischen Azure-VMs liegt die Client-Latenz im 99,9. Perzentil bei aktiviertem Accelerated Networking oft bei unter 300 Mikrosekunden
- Es basiert auf moderner .NET-Technologie und zielt auf eine plattformübergreifende, erweiterbare und moderne Architektur
- Es wurde so entworfen, dass Entwicklung und Weiterentwicklung erleichtert werden, ohne die Performance im Regelfall zu beeinträchtigen
- Es nutzt das .NET-Library-Ökosystem, um die API-Breite zu vergrößern und Spielraum für Optimierungen zu lassen
- Unter Linux und Windows erreicht es Performance auf aktuellem Spitzenniveau
- Falls ein vollständig verwalteter Service benötigt wird, bietet Azure Cosmos DB Garnet Cache Garnet als Enterprise-Caching-Lösung mit hoher Verfügbarkeit, garantierter Performance und ohne Infrastrukturverwaltung an
Kürzlich hinzugefügte Funktionen und Paper
- Vector Sets Preview bietet Approximate-Nearest-Neighbor-Suche
- Sie basiert auf dem DiskANN-Algorithmus und Garnets Tsavorite-Speicher-Engine
- In ersten Ergebnissen zeigt Garnet bessere Werte bei QPS, p99-Latenz und Recall
- Range Index Preview bietet sekundäre Bereichs- und Gleichheitsindizes auf Garnet-Keys
- Sie basiert auf Bf-Tree
- Das Garnet-Paper soll in der VLDB 2026 erscheinen
- Der Titel des Papers lautet Garnet: A Next-Generation Cache-Store for Accelerating Applications and Services
- Ein PDF ist verfügbar
API und Erweiterungsmodell
- Garnet implementiert verschiedene APIs
- rohe Strings: get, set, Key-Ablauf
- analytische Operationen: HyperLogLog, Bitmap
- Objektoperationen: sorted set, list usw.
- Es unterstützt Multi-Key-Transaktionen
- RESP-Transaktionen auf Client-Seite
- serverseitige Stored Procedures und Module auf Basis von C#
- Nutzer können benutzerdefinierte Operationen sowohl für rohe Strings als auch für benutzerdefinierte Objekttypen erstellen
- Durch den Komfort und die Sicherheit von C# wird die Einstiegshürde für die Entwicklung eigener Erweiterungen gesenkt
- Lua-Skripte werden ebenfalls unterstützt
Netzwerk-, Sicherheits- und Speicher-Schicht
- Garnet verwendet eine schnelle und steckbare Netzwerk-Schicht
- Das ermöglicht künftig Erweiterungen wie die Nutzung von Kernel-Bypass-Stacks
- Für sichere Kommunikation wird TLS mithilfe der .NET-Bibliothek SslStream unterstützt
- Es bietet grundlegende Zugriffskontrolle
- Die Speicher-Schicht Tsavorite wurde für hohe Performance entwickelt und umfasst verschiedene Datenbankfunktionen
- Thread-Skalierbarkeit
- tiered Storage mit Speicher, SSD und Cloud-Storage
- schnelle, nicht blockierende Checkpoints
- Recovery
- Operations-Log für Persistenz
- Multi-Key-Transaktionen
- bessere Speicherverwaltung und Wiederverwendung
Architekturdesign
- Das Design von Garnet gestaltet den gesamten Cache-Store-Stack neu – vom Empfang der Netzwerkpakete über das Parsen und Verarbeiten der Datenbankoperationen bis zur Interaktion mit dem Storage
- Die Netzwerk-Schicht basiert auf einem Shared-Memory-Design
- TLS-Verarbeitung und Storage-Interaktionen erfolgen im Thread für den Abschluss von Netzwerk-I/O
- Dadurch wird im Regelfall der Overhead von Thread-Wechseln vermieden
- Statt Daten wie bei traditionellen shuffle-basierten Netzwerkdesigns zum passenden Shard des Servers zu verschieben, sorgt die Kohärenz des CPU-Caches dafür, dass die Daten zur Verarbeitungslogik gelangen
- Das Speicherdesign besteht aus zwei Tsavorite-Key-Value-Stores, die durch einen gemeinsamen Operations-Log verbunden sind
- Der main store ist für rohe String-Operationen optimiert und verwaltet Speicher sorgfältig, um Garbage Collection zu vermeiden
- Der optionale object store ist für komplexe Objekte und benutzerdefinierte Datentypen optimiert
- Der object store umfasst Typen wie Sorted Set, Set, Hash, List und Geo
- Die Datentypen des object store nutzen in der aktuellen Implementierung das .NET-Library-Ökosystem
- Objekte werden im Memory-Heap in einem für Updates effizienten Format und auf der Festplatte in serialisierter Form gespeichert
- Zur Erleichterung künftiger Wartung soll die Nutzung eines einheitlichen Indexes und Logs geprüft werden
- Ein Unterscheidungsmerkmal von Garnet ist die schmale Tsavorite-Storage-API
- Darauf wird eine große, umfangreiche und erweiterbare RESP-API-Oberfläche implementiert
- Sie besteht aus Lese-, upsert-, Lösch- und atomaren read-modify-write-Operationen
- Über asynchrone Callbacks kann die Garnet-Logik an mehreren Punkten jeder Operation eingreifen
- Dadurch werden Parsing- und Query-Verarbeitungsaspekte von Storage-Details wie Nebenläufigkeit, Storage-Tiering und Checkpoints getrennt
- Für Multi-Key-Transaktionen wird Two-Phase Locking verwendet
Cluster-Modus und betriebliche Einschränkungen
- Neben dem Betrieb auf einem einzelnen Knoten unterstützt Garnet auch den Cluster-Modus
- Es können Deployments mit Sharding und Replikation erstellt und verwaltet werden
- Es unterstützt eine effiziente und dynamische Methode zur Key-Migration für das Rebalancing von Shards
- Nutzer können Garnet-Cluster mit Standardbefehlen des Redis-Clusters erstellen und verwalten
- Die Knoten nutzen Gossip, um den Clusterzustand zu teilen und weiterzuentwickeln
- Das Design des Cluster-Modus von Garnet ist derzeit passiv
- Es implementiert keine Leader-Wahl
- Es reagiert auf Cluster-Befehle, die von einer vom Nutzer bereitgestellten Control Plane ausgegeben werden
- Weitere Informationen dazu finden sich in der Control-Plane-Dokumentation
Dokumentation und Lizenz
- Weitere Informationen und Dokumentation finden sich auf der Garnet-Dokumentationsseite
- Für den Einstieg gibt es die Dokumentation getting started
- Release-Informationen stehen im Abschnitt releases
- Das Projekt wird unter der MIT License bereitgestellt
1 Kommentare
Meinungen auf Hacker News
Wenn man sich die Benchmark-Performance-Grafiken (https://microsoft.github.io/garnet/docs/benchmarking/results...) ansieht, ist der GET-Durchsatz mehr als 10-mal höher als bei Dragonfly.
Die 50%-Latenz ist etwas höher als bei Dragonfly, das 99. Perzentil aber etwas niedriger.
Sowohl Garnet als auch Dragonfly sind bei Durchsatz und Latenz deutlich besser als Redis; Redis scheint also erhebliche Performance-Optimierungen zu brauchen.
Ich weiß nicht, ob Optimierung wirklich nötig ist; hier gibt es ja bereits drei Alternativen.
Garnet ist allerdings beeindruckend, weil es die erste Alternative ist, die Redis sowohl bei niedriger als auch bei hoher Parallelität übertrifft, und ich möchte es bald ausprobieren.
Dragonfly ist in C++ geschrieben, Redis in C.
Tsavorite, die Speicherschicht von Garnet, ist aus dem Open-Source-Projekt FASTER hervorgegangen und enthält starke Datenbankfunktionen wie Thread-Skalierbarkeit, hierarchischen Speicher (Arbeitsspeicher, SSD, Cloud-Speicher), schnelle nicht blockierende Checkpoints, Recovery, ein Operations-Log für Haltbarkeit, Multi-Key-Transaktionen sowie besseres Speichermanagement und Wiederverwendung.
https://www.microsoft.com/en-us/research/blog/introducing-ga...
In einem Proof-of-Concept-Projekt mit hohen Performance-Anforderungen, an dem ich damals arbeitete, wirkte es als Persistenzbibliothek recht vielversprechend.
Nebenbei: Beide Projekte scheinen von derselben Person geleitet zu werden [1].
[1]: https://github.com/badrishc
Die Projekte, bei denen Microsoft und das .NET-Team direkt an Infrastruktur herumhacken, sind ziemlich beeindruckend.
Yarp ist ein Tool für Reverse Proxy/API-Gateway/was auch immer man sonst braucht, und Garnet ist nun für In-Memory-Caches gedacht.
Offenbar gibt es intern einen enormen Bedarf und auch den Willen, das zu teilen.
Es wäre schön, wenn so etwas in Azure App Service eingebaut wäre.
Damit man wegen Caching nicht zwingend einen Remote-Dienst verwenden muss.
Früher war es bei IIS üblich, für ASP.NET-Apps einen Out-of-Process-Session-State-Store zu haben.
Das sollte verhindern, dass Nutzer ihre Session verlieren und sich von vorne anmelden müssen, wenn der Web-App-Prozess neu startet.
Natürlich kann man das auch in einem zentralen Store wie SQL Server ablegen, aber dann wartet jede Webpage-Anfrage vor der Verarbeitung auf das Laden des Session State.
Da Session State normalerweise auf irgendeine Weise gesperrt wird, gibt es dabei auch viele Performance-Probleme.
Die heute übliche Lösung ist, Redis für Cache und Session State zu verwenden; das funktioniert meist einigermaßen.
Der Durchsatz ist hoch, aber Redis ist in Azure eine separate Ressource und absurd teuer.
Für etwas so Einfaches möchte ich keine Oracle-DB-Preise zahlen, und die Verbindungskonfiguration ist auch ziemlich umständlich.
In diesem Artikel ist von 300 Mikrosekunden Antwortzeit die Rede, aber bei zonenredundantem Design ist das wenig aussagekräftig, weil alle Azure-Load-Balancer eine zufällige Zonenauswahl verwenden.
Ein Webserver in einer zufälligen Zone wird ausgewählt und verbindet sich dann wieder mit einem Cache-Server in einer zufälligen Zone.
Wenn dieser Server den Schlüssel nicht hat, muss er die Cache-Daten möglicherweise aus einer weiteren zufälligen Zone holen.
Der Traffic pingpongt zwischen Rechenzentren, wodurch 1–3 ms Latenz entstehen — bis zu 10-mal langsamer als die von Garnet beworbenen Zahlen.
Das ideale Szenario wäre etwas wie reliable collections[1] von Microsoft Service Fabric.
Es läuft lokal auf jedem Host-Node und repliziert auf zwei weitere Nodes.
Die Web-App kann Cache-Werte immer vom selben physischen Host lesen.
In manchen Fällen sinkt die Latenz auf einstellige Mikrosekundenwerte, und selbst ein sehr gut optimierter externer Dienst ist mit einfachem Load Balancing tausendfach langsamer.
Ich will nicht 30 % schneller als Redis, sondern 3.000-mal schneller.
[1] https://learn.microsoft.com/en-us/azure/service-fabric/servi...
Man kann Services so konfigurieren, dass sie immer zum lokalen Service gehen, oder auch andere Routing-Topologien nutzen.
Sehr gut für DNS oder Application-Caches.
Ein Redis-Ersatz mit ziemlich beeindruckenden Benchmark-Werten bei Latenz und Durchsatz.
Mich würde interessieren, wie das im echten Betrieb auf einem Nicht-Azure-Stack aussieht.
Ich sehe keinen Hinweis auf xstream-Unterstützung.
Garnet being multi-threaded, MSET is not atomic. For an atomic version of MSET, you would need to express it as a transaction (stored procedure).Diesen Teil verstehe ich nicht ganz.
Warum wird der Befehl intern nicht in eine Transaktion verpackt und dadurch atomar gemacht?
Außerdem würde mich interessieren, welche Atomaritätsfallen es sonst noch gibt.
MSETnicht brauchen, ein Performance-Overhead, und es gäbe keine Möglichkeit, diese Transaktion abzuschalten.Wenn man andererseits einen Drop-in-Ersatz für Redis anstrebt, ist das ein Problem, weil Redis Atomarität garantiert.
Zumindest wenn Drop-in-Ersatz ein Designziel ist, könnte es eine Konfigurationsoption geben, um zwischen Kompatibilität und Performance zu wählen.
Definitiv beeindruckend.
Microsoft Research bringt gelegentlich großartige Projekte hervor; es muss Spaß machen, für Forschung und Entwicklung bezahlt zu werden.
Ich wünschte, große Unternehmen würden mehr F&E-artige Projekte machen, die der ganzen Branche helfen.
Falls Hashicorp zum Verkauf steht, hoffe ich, dass ein gutes Unternehmen sie übernimmt.
Für Leute, die auf Microsoft Windows Server ohne Abhängigkeit von WSL2 direkt einen Redis-kompatiblen Server betreiben müssen, ist das eine sehr gute Nachricht.
Früher gab es einen Redis-Port[1], aber der ist inzwischen archiviert, hatte Probleme mit dem Speicherverbrauch (soweit ich weiß hauptsächlich wegen memory-mapped files) und wird nicht mehr unterstützt.
Dass es in C# geschrieben ist, finde ich persönlich ebenfalls ziemlich interessant.
Da C# meine Hauptsprache ist, möchte ich mir die Zeit nehmen, den Code genauer zu durchforsten.
[1]: https://github.com/microsoftarchive/redis
Ich würde gern sehen, wo das in echten Produktionsumgebungen eingesetzt wird.
Es gibt die Stelle: „Nach Tausenden Unit-Tests und mehreren Jahren Produktionsbetrieb von Garnet mit Microsofts 1st-Party-Teams hatten wir das Gefühl, dass es Zeit ist, es zu veröffentlichen.“
https://microsoft.github.io/garnet/blog
Wenn man sich die Kommentare hier ansieht, scheint heute niemand mehr memcached zu verwenden.
Ich wollte einen LRU-Cache, aber es gab mehrere Optionen und die Erklärungen waren nicht besonders gut, sodass ich nicht verstehen konnte, warum ständig Einträge verdrängt wurden.
Nach dem Wechsel zu Redis war die Konfiguration einfach und es funktionierte wie erwartet.