Eine Organisation, die mehrere Anwendungen parallel betreibt, wiederholt in jeder einzelnen dieselbe teure Arbeit. Eine Datenbankaggregation läuft bei jeder Anfrage neu, statt ihr Ergebnis wiederzuverwenden. Eine externe API-Antwort wird bei jedem Aufruf erneut abgeholt, obwohl sie sich seit Minuten nicht geändert hat. Ein gerenderter Seitenausschnitt entsteht bei jedem Seitenaufruf neu, obwohl hundert Besucher in derselben Minute denselben Ausschnitt sehen. Dazu kommt die Sitzungsverwaltung: Jede Anwendung hält die Anmeldedaten ihrer Nutzer im eigenen Prozessspeicher, dem Arbeitsspeicherbereich, den nur dieser eine laufende Prozess kennt. Ein Neustart der Anwendung oder eine zweite Serverinstanz für mehr Last löscht diesen Speicher restlos, und jeder angemeldete Nutzer muss sich neu anmelden.
Redis ist ein In-Memory-Datenspeicher, ein Server, der seinen gesamten Datenbestand im Arbeitsspeicher hält und dadurch Lese- und Schreibzugriffe im Bereich von Mikrosekunden beantwortet. Statt für jede Anwendung eine eigene, isolierte Cache-Logik und eine eigene bezahlte Cache-Instanz zu betreiben, teilen sich mehrere Anwendungen eine gemeinsame Redis-Instanz und trennen ihre Daten über ein eigenes Schlüsselpräfix je Anwendung. Das senkt die Anzahl der zu betreibenden Cache-Server auf einen einzigen und macht Sitzungen unabhängig vom Prozessspeicher der einzelnen Anwendung, weil sie in einem eigenständigen Server liegen, der einen Neustart der Anwendung übersteht. Ob sich das self-hosten überhaupt lohnt, hängt seit 2024 wesentlich von der Lizenz ab, unter der Redis steht, denn das Projekt hat seine Lizenz in den vergangenen zwei Jahren zweimal geändert.
Systemvoraussetzungen
Die folgende Tabelle listet die aktuellen Versionen und Anforderungen für einen gemeinsam genutzten Redis-Aufbau, Stand der Redis-eigenen Dokumentation und des offiziellen GitHub-Repositorys.
| Komponente | Version oder Anforderung | Zweck |
|---|---|---|
| Redis | Version 8.10.1 (Sicherheits-Release vom 17. August 2026, aktuelle stabile Version), seit Redis 8 zusätzlich unter der AGPLv3-Lizenz verfügbar | Zentraler In-Memory-Datenspeicher für Cache und Sitzungen |
| Docker | Offizielles Image redis:8.10.1 von Docker Hub, Debian- oder Alpine-Basis | Reproduzierbarer, versionsfixierter Betrieb der Instanz |
| Persistenter Datenträger | Gemountetes Docker-Volume für das Verzeichnis /data | Erhält RDB-Snapshot und AOF-Protokoll über Neustarts hinweg |
| Node.js-Client | npm-Paket redis (node-redis), laut Redis-Dokumentation der aktuell empfohlene Client für Node.js und JavaScript | Verbindung jeder einzelnen Anwendung zur gemeinsamen Instanz |
| Schlüsselpräfix je Anwendung | Eigene, projektweit eindeutige Zeichenkette pro Anwendung, zum Beispiel app-a, app-b, app-c | Trennt Cache und Sitzungen mehrerer Anwendungen in derselben Instanz |
| Quelloffene Alternative | Valkey, Version 9.1.1 (21. Juli 2026), BSD-Lizenz, verwaltet von der Linux Foundation | Fork ohne die Netzwerk-Copyleft-Klausel der AGPLv3 |
Systemarchitektur
In einem Aufbau mit mehreren Anwendungen bekommt jede Anwendung kein eigenes Redis, sondern nur ihr eigenes Schlüsselpräfix innerhalb derselben Instanz. Eine Anfrage von Anwendung A prüft zuerst, ob unter ihrem Präfix bereits ein passender Schlüssel liegt. Liegt er vor, ist das ein Cache Hit, ein Treffer, und Redis liefert den gespeicherten Wert sofort zurück, ohne dass die eigentliche Datenquelle angefragt wird. Liegt er nicht vor, ist das ein Cache Miss, ein Fehltreffer: Die Anwendung berechnet das Ergebnis selbst oder fragt es bei ihrer Datenbank ab und legt es danach mit einer Ablaufzeit in Redis ab, bevor sie es zurückgibt. Sitzungsdaten laufen über denselben Mechanismus, nur ohne den Umweg über eine zweite Datenquelle: Die Anwendung schreibt die Sitzung direkt unter ihrem Präfix in Redis und liest sie von dort bei jeder folgenden Anfrage, unabhängig davon, welcher Anwendungsprozess oder welche Serverinstanz die Anfrage gerade bedient.
flowchart TD
A[Anwendung A sendet eine Anfrage] --> D[Schluessel mit Praefix app-a im gemeinsamen Redis]
B[Anwendung B sendet eine Anfrage] --> E[Schluessel mit Praefix app-b im gemeinsamen Redis]
C[Anwendung C sendet eine Anfrage] --> F[Schluessel mit Praefix app-c im gemeinsamen Redis]
D --> G{Schluessel im Speicher vorhanden}
E --> G
F --> G
G -->|Ja, Cache Hit| H[Wert direkt aus dem Speicher liefern]
G -->|Nein, Cache Miss| I[Datenbankabfrage oder Berechnung ausfuehren]
I --> J[Ergebnis mit Ablaufzeit im Speicher ablegen]
J --> H
D --> K[Sitzungsdaten bleiben nach einem Neustart der Anwendung erhalten]
Die drei Anwendungen A, B und C teilen sich denselben Redis-Prozess, denselben Arbeitsspeicher und dieselbe Netzwerkverbindung, bleiben aber durch ihr jeweiliges Präfix logisch getrennt. Ein Ausfall oder Neustart der Redis-Instanz betrifft zwar alle drei gleichzeitig, ein einzelner Fehler in Anwendung A verändert dagegen nie die Schlüssel von Anwendung B oder C, solange jede Anwendung ausschließlich unter ihrem eigenen Präfix schreibt und liest.
Schritt-für-Schritt-Umsetzung
Redis mit Docker und aktivierter Persistenz starten
Ein einzelner docker run-Befehl reicht, um Redis mit dem offiziellen Image, einem persistenten Datenträger und einer Speichergrenze zu starten. Ohne die Option --appendonly yes bleibt die AOF-Persistenz (Append Only File, ein fortlaufendes Protokoll jedes schreibenden Befehls) deaktiviert, weil appendonly no laut der mit Redis 8.10.1 ausgelieferten Konfigurationsdatei die Voreinstellung ist. Ohne einen gemounteten Datenträger unter /data gehen selbst die automatisch erzeugten RDB-Snapshots, binäre Momentaufnahmen des gesamten Datenbestands, beim Löschen des Containers verloren, weil sie nur im beschreibbaren Containerdateisystem liegen. Drei Schritte reichen für eine erste Instanz.
- Ein benanntes Docker-Volume für das Datenverzeichnis anlegen. Ein Volume mit dem Namen
redis-dataübersteht das Löschen und Neuerstellen des Containers, anders als das Containerdateisystem selbst. - Den Container mit Persistenz- und Speicherflags starten.
--appendonly yesaktiviert die AOF-Protokollierung,--maxmemoryund--maxmemory-policysetzen die Speichergrenze und die Räumregel dafür. - Die aktive Konfiguration im laufenden Container bestätigen. Ein
CONFIG GETüberredis-clizeigt den im laufenden Prozess wirksamen Wert, statt sich auf die Startparameter allein zu verlassen.
docker run -d \
--name redis-shared \
-p 6379:6379 \
-v redis-data:/data \
redis:8.10.1 \
redis-server --appendonly yes --maxmemory 512mb --maxmemory-policy allkeys-lru
Die Option --appendonly yes schaltet die AOF-Persistenz ein, sodass jeder schreibende Befehl fortlaufend protokolliert wird und sich beim Start aus dem Protokoll wiederherstellen lässt. Redis legt zusätzlich weiterhin automatisch RDB-Snapshots an, sofern kein leerer save-Wert gesetzt wurde: In der mit Redis ausgelieferten Voreinstellung entsteht ein Snapshot nach einer Stunde bei mindestens einer Änderung, nach fünf Minuten bei mindestens hundert Änderungen und nach einer Minute bei mindestens zehntausend Änderungen. --maxmemory 512mb begrenzt den Arbeitsspeicher, den Redis für den Datenbestand verwendet, und --maxmemory-policy allkeys-lru legt fest, welche Schlüssel Redis entfernt, sobald diese Grenze erreicht ist. Ein Blick in die laufende Konfiguration bestätigt beide Einstellungen.
docker exec redis-shared redis-cli CONFIG GET appendonly
docker exec redis-shared redis-cli CONFIG GET maxmemory-policy
Jede Anwendung über ein eigenes Schlüsselpräfix trennen
Redis bietet für die Trennung mehrerer Datensätze zwei unterschiedliche Mechanismen, und nur einer davon eignet sich für mehrere unabhängige Anwendungen. Der erste Mechanismus sind 16 nummerierte logische Datenbanken, in der Standardeinstellung durchnummeriert von 0 bis 15 und über die Konfigurationsdirektive databases veränderbar; der Befehl SELECT <index> wechselt die aktuell verwendete Datenbank für die jeweilige Verbindung. Die eigene Redis-Dokumentation empfiehlt diesen Weg für den hier beschriebenen Fall ausdrücklich nicht: Nummerierte Datenbanken sollen Schlüssel innerhalb ein und derselben Anwendung trennen, nicht mehrere voneinander unabhängige Anwendungen in einer Instanz. Ein zusätzlicher, praktischer Grund kommt hinzu, sobald eine der Anwendungen wächst: Der Redis-Cluster-Modus, der eine Instanz über mehrere Knoten hinweg skaliert, unterstützt ausschließlich Datenbank 0 und lehnt den SELECT-Befehl für jeden anderen Index ab.
Der zweite Mechanismus, das Schlüsselpräfix, funktioniert dagegen unabhängig davon, ob Redis später als einzelner Prozess oder als Cluster läuft. Jede Anwendung erhält eine eigene, projektweit eindeutige Zeichenkette und stellt sie jedem ihrer Schlüssel voran, getrennt durch einen Doppelpunkt als Konvention.
app-a:session:8f3c1e9b2a
app-a:cache:product-aggregation:4711
app-b:session:2b91af0c7d
app-b:cache:homepage-fragment
app-c:session:7a44d0e912
Alle fünf Schlüssel liegen in derselben Datenbank 0 desselben Redis-Prozesses. Ein Befehl wie KEYS app-b:* oder das für den Produktivbetrieb geeignetere, weil nicht blockierende SCAN mit demselben Muster liefert dabei ausschließlich die Schlüssel von Anwendung B, ohne dass Anwendung A oder C etwas davon mitbekommen.
Sessions und Cache-Aside-Muster mit Node.js anbinden
Node-redis, das npm-Paket redis, ist laut Redis-eigener Dokumentation der aktuell empfohlene Client für Node.js- und JavaScript-Anwendungen. Die Verbindung steht nach dem Aufruf von connect() auf dem zurückgegebenen Client-Objekt, das anschließend von jeder Funktion der Anwendung wiederverwendet wird.
import { createClient } from 'redis';
const APP_PREFIX = 'app-a';
const redisClient = createClient({
url: process.env.REDIS_URL || 'redis://localhost:6379',
});
redisClient.on('error', (err) => console.error('Redis-Verbindungsfehler', err));
await redisClient.connect();
Eine Sitzung liegt unter dem Präfix der Anwendung als JSON-Zeichenkette mit einer Ablaufzeit (TTL, Time to Live), nach der Redis den Schlüssel automatisch entfernt. Die Option EX beim SET-Befehl setzt diese Ablaufzeit in Sekunden und ersetzt den älteren, funktional identischen Befehl SETEX.
async function saveSession(sessionId, data, ttlSeconds = 1800) {
await redisClient.set(
`${APP_PREFIX}:session:${sessionId}`,
JSON.stringify(data),
{ EX: ttlSeconds },
);
}
async function getSession(sessionId) {
const raw = await redisClient.get(`${APP_PREFIX}:session:${sessionId}`);
return raw ? JSON.parse(raw) : null;
}
Das Cache-Aside-Muster folgt derselben Logik für berechnete Ergebnisse statt für Sitzungen: Die Anwendung fragt zuerst Redis, und nur bei einem Fehltreffer führt sie die teure Datenbankabfrage oder Berechnung aus.
async function getProductAggregation(productId) {
const cacheKey = `${APP_PREFIX}:cache:product-aggregation:${productId}`;
const cached = await redisClient.get(cacheKey);
if (cached) {
return JSON.parse(cached);
}
const fresh = await computeExpensiveAggregation(productId);
await redisClient.set(cacheKey, JSON.stringify(fresh), { EX: 300 });
return fresh;
}
Die Ablaufzeit von 300 Sekunden im Beispiel legt fest, wie veraltet das gecachte Ergebnis im schlechtesten Fall sein darf, bevor die nächste Anfrage die Berechnung erneut auslöst. Anwendung B und Anwendung C führen exakt denselben Code mit einem anderen Wert für APP_PREFIX gegen dieselbe Redis-Instanz aus, ohne dass sich ihre Schlüssel jemals überschneiden.
Häufige Fehlerquellen
- Eine Anwendung löscht mit FLUSHALL oder FLUSHDB die Daten aller anderen mit.
FLUSHALLentfernt laut Redis-Dokumentation sämtliche Schlüssel aus allen Datenbanken der Instanz auf einmal, nicht nur die der aufrufenden Anwendung, undFLUSHDBleert zumindest die gesamte aktuell gewählte Datenbank. Beide Befehle lassen sich von jedem verbundenen Client ohne Rückfrage ausführen, sobald keine Berechtigung dagegenspricht. Fix: Über eine Redis-ACL (Access Control List) je Anwendung einen eigenen Benutzer anlegen, demFLUSHALLundFLUSHDBausdrücklich verboten sind, statt alle Anwendungen mit dem Standardbenutzer arbeiten zu lassen. - Persistenz bleibt auf der Voreinstellung, und ein Neustart löscht alle Sitzungen gleichzeitig. Ohne
appendonly yesund ohne gemounteten Datenträger unter/dataverliert Redis beim Neustart des Containers seinen gesamten Datenbestand, weilappendonly nodie Standardeinstellung ist und ein neuer Container ohne Volume mit einem leeren Dateisystem beginnt. Symptom: Alle angemeldeten Nutzer aller angeschlossenen Anwendungen werden gleichzeitig abgemeldet, sobald die Redis-Instanz aktualisiert oder neu gestartet wird. Fix:--appendonly yessetzen und/dataauf ein Docker-Volume oder einen anderen dauerhaften Speicherort mounten, bevor die Instanz produktiv genutzt wird. - Zwei Anwendungen wählen Präfixe, die sich beim Mustervergleich überschneiden. Ein Präfix
appohne Trennzeichen matcht bei einem Muster wieapp*auch Schlüssel einer später hinzugekommenen Anwendungapp2, was Wartungsskripte auf die falschen Schlüssel zugreifen lässt. Fix: Jedes Präfix fest mit einem Doppelpunkt abschließen (app-a:) und neue Präfixe vor der Vergabe gegen eine zentrale Liste bereits vergebener Präfixe prüfen. - Kein Grenzwert für maxmemory gesetzt, und der Prozess wächst unkontrolliert. Ohne
maxmemorygilt laut Redis-Dokumentation auf 64-Bit-Systemen keine Grenze, sodass der Redis-Prozess so lange wächst, bis der Arbeitsspeicher des Hosts erschöpft ist und das Betriebssystem den Prozess über den Out-of-Memory-Killer beendet. Das reißt dann alle angeschlossenen Anwendungen gleichzeitig aus dem Cache, nicht nur die, die den Speicher zuletzt gefüllt hat. Fix:maxmemoryvon Anfang an explizit setzen, zusammen mit einer zum Anwendungsfall passenden Richtlinie wieallkeys-lru. - SELECT und nummerierte Datenbanken statt Präfixen verwendet, und der Wechsel zu Redis Cluster scheitert. Eine Konfiguration, die Anwendungen über
SELECT 1,SELECT 2und so weiter trennt, läuft auf einer einzelnen Redis-Instanz zunächst unauffällig, bricht aber vollständig, sobald die Instanz später auf einen Redis-Cluster zur horizontalen Skalierung umgestellt wird, weil der Cluster-Modus nur Datenbank 0 unterstützt. Fix: Von Beginn an Schlüsselpräfixe in Datenbank 0 verwenden, auch wenn aktuell nur eine einzelne Instanz ohne Cluster geplant ist.
Häufig gestellte Fragen
Was passiert mit Sitzungsdaten in Redis, wenn der Server ohne aktivierte Persistenz neu startet?
Sitzungsdaten in Redis gehen bei einem Neustart vollständig verloren, wenn weder die AOF-Protokollierung noch RDB-Snapshots aktiv sind, weil Redis den gesamten Datenbestand ausschließlich im Arbeitsspeicher hält. Die Einstellung appendonly no ist laut der mit Redis 8.10.1 ausgelieferten Konfigurationsdatei die Voreinstellung, sodass die AOF-Protokollierung manuell mit appendonly yes eingeschaltet werden muss. Selbst mit den unveränderten Standard-Snapshot-Punkten (nach einer Stunde bei einer Änderung, nach fünf Minuten bei hundert Änderungen, nach einer Minute bei zehntausend Änderungen) gehen alle Schreibvorgänge seit dem letzten Snapshot verloren, sobald der Prozess ohne sauberes Herunterfahren endet.
Ist Redis heute noch eine echte Open-Source-Software, oder gilt wieder eine kommerzielle Lizenz?
Redis ist seit dem 1. Mai 2025 wieder unter einer von der Open Source Initiative anerkannten Lizenz verfügbar, nachdem das Projekt im März 2024 zunächst auf die Server Side Public License und die Redis Source Available License umgestellt hatte und damit den Status als vollständig quelloffene Software verloren hatte. Seit Redis 8 steht der Quellcode zusätzlich unter der AGPLv3 (GNU Affero General Public License Version 3), einer Lizenz mit einer Netzwerk-Copyleft-Klausel: Wer eine modifizierte Version über das Netzwerk als Dienst anbietet, muss auch diese Änderungen offenlegen. Organisationen, die genau diese Klausel vermeiden wollen, weichen häufig auf Valkey aus, den 2024 von der Linux Foundation übernommenen Fork unter der permissiven BSD-Lizenz, der in Version 9.1.1 vom 21. Juli 2026 inzwischen auch bei großen Cloud-Anbietern die Standardauswahl für neu angelegte verwaltete Cache-Dienste ist.
Wie trennt eine gemeinsam genutzte Redis-Instanz die Daten mehrerer Anwendungen voneinander?
Eine gemeinsam genutzte Redis-Instanz trennt die Daten mehrerer Anwendungen in der Praxis über ein eigenes Schlüsselpräfix je Anwendung, etwa app-a: und app-b: vor jedem Schlüsselnamen. Redis besitzt zwar mit den 16 nummerierten logischen Datenbanken (Index 0 bis 15 in der Standardeinstellung) und dem SELECT-Befehl einen eingebauten zweiten Mechanismus, die eigene Dokumentation empfiehlt ihn für diesen Zweck aber ausdrücklich nicht und reserviert ihn für die Trennung von Schlüsseln innerhalb ein und derselben Anwendung. Ein weiterer Grund gegen nummerierte Datenbanken bei mehreren Anwendungen: Der Redis-Cluster-Modus für horizontale Skalierung unterstützt ausschließlich Datenbank 0, sodass eine auf SELECT aufgebaute Trennung bei einem späteren Umstieg auf Cluster-Betrieb vollständig neu aufgebaut werden müsste.
Kann eine Anwendung versehentlich die Cache- und Sitzungsdaten aller anderen Anwendungen in derselben Redis-Instanz löschen?
Eine Anwendung kann mit einem einzigen FLUSHALL-Befehl die Daten aller anderen Anwendungen in derselben Redis-Instanz löschen, weil dieser Befehl laut Redis-Dokumentation sämtliche Schlüssel aus allen Datenbanken auf einmal entfernt und dabei nicht zwischen Anwendungen unterscheidet. Der verwandte Befehl FLUSHDB leert zumindest nur die aktuell gewählte Datenbank, trifft bei einer Trennung über Präfixe in Datenbank 0 aber ebenfalls alle Anwendungen gleichzeitig, weil sie sich dieselbe Datenbank teilen. Beide Befehle lassen sich ohne Rückfrage von jedem Client mit ausreichenden Rechten ausführen; der wirksame Schutz besteht darin, sie über eine Redis-ACL für die Benutzer der einzelnen Anwendungen ausdrücklich zu sperren, statt sich auf Vorsicht beim Schreiben von Wartungsskripten zu verlassen.