JSONPath-Zugriff statt kompletter Serialisierung
Wer JSON-Daten bisher als String in Redis abgelegt hat, kennt das Problem: Jede noch so kleine Änderung an einem einzelnen Feld erfordert, das komplette Dokument zu laden, zu deserialisieren, zu ändern und wieder als Ganzes zurückzuschreiben. RedisJSON löst dieses Problem, indem es JSON-Dokumente als eigenen, nativen Datentyp verwaltet und über JSONPath-Ausdrücke gezielten Zugriff auf einzelne Pfade erlaubt, ohne das gesamte Dokument zu bewegen.
Inhaltsverzeichnis
- 1. Das Problem mit String-basiertem JSON in Redis
- 2. RedisJSON als eigener Datentyp im Redis Stack
- 3. JSONPath: Gezielter Lesezugriff ohne das gesamte Dokument zu laden
- 4. Atomare Teil-Updates statt Read-Modify-Write
- 5. Performance im Vergleich zu String-basiertem JSON
- 6. Praxisbeispiel: Produktkonfigurationsdaten strukturiert speichern
- 7. Kombination mit RediSearch: Indizierte Abfragen über JSON-Dokumente
- 8. Persistenz und Speicherverbrauch von JSON-Dokumenten
- 9. Client-Integration in PHP- und Magento-Umgebungen
- 10. Zusammenfassung
- 11. FAQ
1. Das Problem mit String-basiertem JSON in Redis
Ohne RedisJSON gibt es in Redis nur eine Möglichkeit, ein JSON-Dokument zu speichern: als serialisierter String über SET und GET. Für Redis selbst ist der Inhalt dabei bedeutungslos, es handelt sich schlicht um eine Byte-Folge. Jede Anwendung, die auch nur ein einzelnes Feld eines Dokuments lesen oder ändern möchte, muss den kompletten String übertragen, im Client deserialisieren, die gewünschte Änderung vornehmen und das gesamte Dokument wieder serialisiert zurückschreiben.
Bei kleinen Dokumenten fällt dieser Umweg kaum ins Gewicht, bei größeren, verschachtelten Strukturen, etwa Produktkonfigurationen mit mehreren hundert Attributen und Varianten, summiert sich der Aufwand jedoch spürbar. Zusätzlich entsteht ein Race-Condition-Risiko: Zwei parallele Prozesse, die dasselbe Dokument lesen, ändern und zurückschreiben, überschreiben sich gegenseitig, wenn nicht zusätzlich mit WATCH, MULTI und EXEC oder Lua-Skripten gegen konkurrierende Schreibzugriffe abgesichert wird.
2. RedisJSON als eigener Datentyp im Redis Stack
RedisJSON ist ein Modul, das seit Redis Stack fest zum Standardpaket gehört und in Redis Enterprise sowie bei den meisten Managed-Redis-Anbietern verfügbar ist. Es führt einen neuen Datentyp ein, der JSON-Dokumente intern als Baum aus Werten abbildet, ähnlich wie es Dokumentendatenbanken tun, nur innerhalb der bekannten Redis-Infrastruktur mit ihrer gewohnten Latenz und ihrem Persistenzmodell.
Der zentrale Unterschied zu String-basiertem JSON zeigt sich schon beim Anlegen: JSON.SET erwartet neben dem Key auch einen JSONPath, an dem das Dokument oder ein Teilbereich davon geschrieben wird. Das gesamte Dokument mit dem Pfad $ zu adressieren funktioniert weiterhin wie ein klassisches SET, doch ab hier öffnet sich die eigentliche Stärke des Moduls: gezielter Zugriff auf einzelne Knoten des Baums.
redis-cli JSON.SET produkt:4711 $ '{"sku":"SHIRT-BLAU-M","name":"Basic Shirt Blau","preis":29.90,"lager":{"gesamt":140,"reserviert":12},"varianten":["S","M","L","XL"]}'
redis-cli JSON.GET produkt:4711 $.preis
# [29.9]
redis-cli JSON.TYPE produkt:4711 $.varianten
# ["array"]
3. JSONPath: Gezielter Lesezugriff ohne das gesamte Dokument zu laden
JSONPath-Ausdrücke erlauben es, exakt den Teil eines Dokuments anzufragen, der gebraucht wird. Statt produkt:4711 komplett zu laden, um nur den reservierten Lagerbestand zu prüfen, genügt JSON.GET produkt:4711 $.lager.reserviert. Bei Dokumenten mit vielen Kilobyte an Nutzdaten, etwa ausführlichen Produktbeschreibungen mit mehrsprachigen Attributen, reduziert das die übertragene Datenmenge drastisch und senkt entsprechend die Netzwerklatenz zwischen Anwendung und Redis-Instanz.
RedisJSON unterstützt sowohl die eingeschränkte, legacy-kompatible Pfadsyntax als auch das vollständige JSONPath mit Wildcards, Filtern und rekursiver Suche über die $-Notation. Damit lassen sich auch Abfragen wie alle Varianten mit einem Lagerbestand unter einem Schwellenwert formulieren, ohne die Filterlogik in die Anwendung auslagern zu müssen, was insbesondere bei stark lesenden Workloads die Client-Seite deutlich entlastet.
redis-cli JSON.GET produkt:4711 '$.varianten[?(@.lager<5)]'
redis-cli JSON.GET produkt:4711 $.lager.reserviert
# [12]
4. Atomare Teil-Updates statt Read-Modify-Write
Der praktische Kernvorteil von RedisJSON liegt bei Schreibzugriffen. Befehle wie JSON.SET mit einem spezifischen Pfad, JSON.NUMINCRBY für numerische Felder oder JSON.ARRAPPEND für Arrays ändern gezielt einen Teilbereich des Dokuments, atomar und ohne dass die Anwendung das gesamte Dokument vorher laden muss. Ein Lagerbestand lässt sich damit direkt im Redis-Server dekrementieren, ganz ohne Read-Modify-Write-Zyklus im Anwendungscode.
Das eliminiert die vorhin beschriebene Race Condition strukturell, weil Redis selbst für die Atomarität der Pfad-Operation sorgt. Zwei parallele Bestellprozesse, die gleichzeitig JSON.NUMINCRBY produkt:4711 $.lager.reserviert 1 ausführen, konkurrieren nicht miteinander. Jeder Aufruf wird serialisiert im Single-Threaded-Command-Loop von Redis verarbeitet, das Ergebnis ist immer konsistent, ganz ohne zusätzliches Locking im Anwendungscode.
redis-cli JSON.NUMINCRBY produkt:4711 $.lager.reserviert 1
redis-cli JSON.ARRAPPEND produkt:4711 $.varianten '"XXL"'
redis-cli JSON.GET produkt:4711 $.lager
# [{"gesamt":140,"reserviert":13}]
5. Performance im Vergleich zu String-basiertem JSON
Der Geschwindigkeitsgewinn von RedisJSON entsteht nicht dadurch, dass das Modul grundsätzlich schneller serialisiert als eine Anwendung, sondern dadurch, dass bei Teilzugriffen die komplette Serialisierung und Deserialisierung schlicht entfällt. Bei einem zehn Kilobyte großen Dokument, von dem nur ein einzelnes Preisfeld gelesen wird, überträgt String-basiertes JSON immer die vollen zehn Kilobyte über das Netzwerk und muss sie clientseitig parsen, RedisJSON überträgt nur die wenigen Bytes des angefragten Pfads.
Bei Schreibzugriffen verstärkt sich der Effekt weiter: Ein String-Update erfordert immer das komplette Dokument als neuen Wert, RedisJSON aktualisiert intern nur den betroffenen Teilbaum. Bei sehr großen Dokumenten mit vielen Kilobyte und häufigen kleinen Änderungen, etwa laufend aktualisierten Lagerbeständen in Produktkatalogen mit tausenden Artikeln, macht sich dieser Unterschied in Benchmarks deutlich in Latenz und Netzwerk-Durchsatz bemerkbar.
6. Praxisbeispiel: Produktkonfigurationsdaten strukturiert speichern
Ein typischer Anwendungsfall im E-Commerce-Kontext sind Produktkonfigurationen mit verschachtelten Attributen: Basisdaten, Preisstufen je Kundengruppe, Varianten mit eigenem Lagerbestand und Metadaten für unterschiedliche Verkaufskanäle. Statt diese Struktur in mehrere flache Redis-Keys aufzuteilen oder als einzelnen JSON-String zu cachen, bildet RedisJSON die gesamte Struktur in einem Dokument ab, das sich gezielt pro Pfad lesen und schreiben lässt.
In der Praxis bedeutet das: Ein Konfigurator-Frontend fragt beim Laden nur die für die Anzeige relevanten Pfade ab, etwa Preise und Verfügbarkeit je Variante, während ein Hintergrundjob, der Lagerbestände synchronisiert, ausschließlich die betroffenen Zahlenfelder mit JSON.NUMINCRBY aktualisiert. Beide Zugriffsarten laufen unabhängig voneinander, ohne sich gegenseitig durch volle Dokument-Overwrites zu blockieren oder zu überschreiben.
{
"sku": "JACKE-SOMMER-42",
"name": "Sommerjacke Leicht",
"preisstufen": {
"standard": 89.90,
"haendler": 62.00,
"vip": 74.90
},
"varianten": [
{"größe": "M", "farbe": "blau", "lager": 34},
{"größe": "L", "farbe": "blau", "lager": 12}
],
"kanaele": ["web", "marketplace", "b2b-portal"]
}
7. Kombination mit RediSearch: Indizierte Abfragen über JSON-Dokumente
RedisJSON entfaltet seine volle Stärke oft erst in Kombination mit dem RediSearch-Modul, das Sekundärindizes direkt auf JSON-Dokumenten anlegen kann. Während RedisJSON den effizienten Zugriff per Key und Pfad ermöglicht, erlaubt RediSearch Abfragen über Attribute hinweg, etwa alle Produkte einer Kategorie mit einem Lagerbestand über einem Schwellenwert, ohne dass die Anwendung selbst über alle Keys iterieren muss.
Diese Kombination ersetzt in vielen Fällen keinen dedizierten Suchindex, reduziert aber den Bedarf an zusätzlicher Infrastruktur für einfache, attributbasierte Filterabfragen erheblich. Wer bereits RedisJSON für die Datenhaltung nutzt und nur gelegentlich über wenige Felder filtern muss, spart sich damit unter Umständen eine separate Elasticsearch- oder OpenSearch-Instanz für diesen Teilbereich der Anwendung.
8. Persistenz und Speicherverbrauch von JSON-Dokumenten
RedisJSON-Dokumente werden wie jeder andere Redis-Datentyp über die konfigurierte Persistenzstrategie gesichert, also über RDB-Snapshots, AOF oder eine Kombination aus beidem. Für den Server ist ein JSON-Dokument dabei kein Sonderfall, es wird beim Snapshot ebenso serialisiert wie eine Hash- oder Sorted-Set-Struktur, sodass sich an bestehenden Backup- und Replikationsprozessen nichts ändert.
Beim Speicherverbrauch lohnt sich ein genauer Blick: Die interne Baumstruktur von RedisJSON benötigt pro Knoten zusätzlichen Verwaltungs-Overhead gegenüber einem rohen, komprimierten JSON-String. Bei sehr vielen kleinen, tief verschachtelten Dokumenten kann der Speicherbedarf spürbar über dem eines vergleichbaren String-basierten Ansatzes liegen, was bei der Kapazitätsplanung für große Produktkataloge explizit berücksichtigt werden sollte, etwa über MEMORY USAGE-Stichproben auf repräsentativen Keys.
redis-cli MEMORY USAGE produkt:4711 SAMPLES 0
9. Client-Integration in PHP- und Magento-Umgebungen
Für die Anbindung an PHP-Anwendungen bieten sowohl phpredis, sofern mit RedisJSON-Unterstützung kompiliert, als auch Predis über generische Command-Aufrufe Zugriff auf die JSON.*-Befehle. In Magento-Kontexten lohnt sich RedisJSON vor allem für eigene, außerhalb des Standard-Cache-Frameworks liegende Datenstrukturen, etwa individuell aufgebaute Konfigurations- oder Feature-Flag-Speicher, weniger für den ohnehin durch das Framework abstrahierten Full-Page-Cache oder Session-Storage.
Ein häufiger Stolperstein in der Praxis: RedisJSON ist kein Bestandteil des Standard-Redis-Servers, sondern muss als Modul explizit geladen werden, entweder über Redis Stack oder eine manuell kompilierte .so-Datei. Wer RedisJSON in einer Produktionsumgebung einsetzen will, sollte vorab prüfen, ob der genutzte Managed-Service oder das Docker-Image das Modul tatsächlich mitbringt, denn ein fehlendes Modul führt bei JSON.SET nicht zu einem hilfreichen Fehler, sondern schlicht zu einem unbekannten Befehl.
redis-cli MODULE LIST
# 1) "name" "ReJSON" "ver" 20602
| Aspekt | String-basiertes JSON | RedisJSON |
|---|---|---|
| Teilfeld lesen | Komplettes Dokument laden und clientseitig parsen | Direkter Zugriff per JSONPath ohne volle Deserialisierung |
| Teilfeld schreiben | Read-Modify-Write-Zyklus im Anwendungscode nötig | Atomares JSON.SET oder JSON.NUMINCRBY auf den Pfad |
| Race Conditions bei parallelen Writes | Nur mit WATCH, MULTI und EXEC oder Lua vermeidbar | Strukturell ausgeschlossen durch Pfad-Atomarität |
| Netzwerklast bei großen Dokumenten | Immer die volle Dokumentgröße | Nur die Größe des angefragten Pfads |
| Verfügbarkeit | In jedem Redis-Server ohne Zusatzmodul | Erfordert Redis Stack oder RedisJSON-Modul |
| Kombinierbarkeit mit Indizierung | Nur über externe Indizes möglich | Direkte Indizierung über RediSearch auf demselben Dokument |
Mironsoft
Cache-Layer-Setup und Magento-Redis-Integration
Magento-Cache, der nicht richtig greift oder falsch konfiguriert ist?
Wir richten Redis als Cache- und Session-Backend für Magento sauber ein, tunen Speicherverbrauch und Eviction-Strategien und sorgen dafür, dass Full Page Cache und Session-Storage zuverlässig zusammenspielen.
Redis-Setup
Cache-, Session- und FPC-Backend produktionsreif für Magento konfigurieren.
Memory-Tuning
Speicherverbrauch und Eviction-Policies auf die tatsächliche Shop-Last abstimmen.
High-Availability-Setup
Redis Sentinel oder Cluster für ausfallsichere Magento-Umgebungen einrichten.
10. Zusammenfassung
RedisJSON: Das Wichtigste auf einen Blick
Datentyp
Eigener JSON-Dokumenttyp mit Baumstruktur statt serialisiertem String
Kernbefehle
JSON.SET, JSON.GET, JSON.NUMINCRBY, JSON.ARRAPPEND mit JSONPath-Adressierung
Typischer Einsatz
Verschachtelte Konfigurationsdaten mit häufigen Teil-Updates, etwa Produktvarianten
Grenzen
Zusätzlicher Speicher-Overhead pro Knoten, erfordert Redis Stack oder eigenes Modul