welche Eviction wann passt
Eine falsch gewählte maxmemory-policy führt entweder zu abgelehnten Schreibvorgängen mitten im Betrieb oder zum stillen Verlust wichtiger Daten, die eigentlich dauerhaft gespeichert werden sollten. Wer versteht, wie Redis Speicher unter Druck verwaltet, wählt die passende Policy gezielt statt zufällig und vermeidet beide Szenarien zuverlässig.
Inhaltsverzeichnis
- 1. Was eine maxmemory-policy wirklich steuert
- 2. Die acht maxmemory-Policies im Überblick
- 3. noeviction: wenn Redis Schreibvorgänge verweigert
- 4. allkeys-lru und volatile-lru im Detail
- 5. allkeys-lfu und volatile-lfu: Häufigkeit statt Aktualität
- 6. volatile-ttl und volatile-random
- 7. Die richtige maxmemory-policy für reine Caches
- 8. maxmemory-policy für Primary Store und Mischbetrieb
- 9. Monitoring, Benchmarking und Umschalten im Betrieb
- 10. Zusammenfassung
- 11. FAQ
1. Was eine maxmemory-policy wirklich steuert
Sobald Redis das in maxmemory konfigurierte Speicherlimit erreicht, muss die Engine entscheiden, was mit neuen Schreibvorgängen passiert. Genau diese Entscheidung wird durch die maxmemory-policy festgelegt. Sie ist keine Nebeneinstellung, sondern eine der folgenreichsten Konfigurationen in jedem Redis-Deployment, weil sie direkt bestimmt, ob Daten verworfen werden dürfen und nach welchem Kriterium das geschieht. Ohne bewusst gesetzte maxmemory-policy läuft Redis mit dem Standardwert noeviction, was für viele produktive Setups die falsche Wahl ist.
Die Auswahl der richtigen maxmemory-policy hängt vollständig davon ab, wofür Redis eingesetzt wird. Dient die Instanz als reiner Cache vor einer relationalen Datenbank, ist Datenverlust bei Speicherdruck unkritisch, solange die richtigen Daten verdrängt werden. Dient Redis hingegen als Primary Store für Sessions, Zähler oder Queues, ist jeder unkontrollierte Datenverlust ein Vorfall. Diese Unterscheidung zieht sich durch den gesamten Artikel und ist der wichtigste Faktor bei der Wahl der maxmemory-policy.
Technisch greift die maxmemory-policy erst, wenn used_memory die konfigurierte Grenze überschreitet und ein neuer Schreibbefehl zusätzlichen Speicher benötigen würde. Redis prüft dann vor jedem Befehl, ob Speicher freigegeben werden muss, wählt nach der aktiven Policy Kandidaten aus und entfernt sie, bevor der eigentliche Befehl ausgeführt wird. Dieser Ablauf passiert synchron im Event-Loop, weshalb die Wahl der maxmemory-policy auch einen direkten Einfluss auf die Latenz einzelner Befehle hat.
2. Die acht maxmemory-Policies im Überblick
Redis bietet acht mögliche Werte für maxmemory-policy, die sich in zwei Dimensionen unterscheiden: den Schlüsselbereich, aus dem Kandidaten gewählt werden, und das Kriterium, nach dem verdrängt wird. Der Schlüsselbereich ist entweder allkeys, was sämtliche Schlüssel einschließt, oder volatile, was nur Schlüssel mit gesetztem TTL berücksichtigt. Das Kriterium ist LRU, LFU, TTL, Random oder gar keine Verdrängung. Diese Kombination ergibt die acht Optionen, die jede maxmemory-policy-Entscheidung im Kern abbildet.
Wichtig ist, die Namenskonvention korrekt zu lesen: allkeys-lru bedeutet, aus allen Schlüsseln wird nach Least-Recently-Used verdrängt, unabhängig davon, ob ein TTL gesetzt ist. volatile-lru wendet dasselbe Kriterium nur auf Schlüssel mit TTL an. Schlüssel ohne Ablaufzeit bleiben bei jeder volatile-Variante der maxmemory-policy unangetastet, selbst wenn der Speicher voll ist. Wird bei einer volatile-Policy kein Schlüssel mit TTL gefunden, verhält sich Redis wie noeviction und lehnt Schreibvorgänge ab.
# redis.conf: maxmemory-policy grundlegend konfigurieren
maxmemory 2gb
maxmemory-policy allkeys-lru
# Verfügbare Werte für maxmemory-policy:
# noeviction: keine Verdrängung, Schreibfehler bei vollem Speicher
# allkeys-lru: LRU über alle Schlüssel
# volatile-lru: LRU nur über Schlüssel mit TTL
# allkeys-lfu: LFU (Zugriffshäufigkeit) über alle Schlüssel
# volatile-lfu: LFU nur über Schlüssel mit TTL
# allkeys-random: zufällige Auswahl über alle Schlüssel
# volatile-random: zufällige Auswahl nur über Schlüssel mit TTL
# volatile-ttl: kürzeste Restlebensdauer zuerst
3. noeviction: wenn Redis Schreibvorgänge verweigert
Die Policy noeviction ist der Standardwert und die konservativste Option unter allen maxmemory-policy-Varianten. Erreicht der Speicher das konfigurierte Limit, akzeptiert Redis keine neuen Schreibbefehle mehr und antwortet mit dem Fehler OOM command not allowed when used memory > maxmemory. Lesebefehle funktionieren weiterhin normal, nur Befehle, die zusätzlichen Speicher beanspruchen, werden abgelehnt. Diese maxmemory-policy ist die richtige Wahl, wenn Datenverlust grundsätzlich inakzeptabel ist und die Anwendung stattdessen einen Fehler sauber behandeln kann.
In der Praxis ist noeviction vor allem für Redis-Instanzen sinnvoll, die als Primary Store für kritische Zustände dienen, etwa Warenkorb-Daten, verteilte Locks oder Zähler mit Geschäftsrelevanz. Der Nachteil dieser maxmemory-policy ist offensichtlich: Ohne aktive Kapazitätsplanung führt sie zu einem produktiven Ausfall, sobald der Speicher erschöpft ist. Anwendungen müssen den OOM-Fehler explizit abfangen, sonst propagiert sich der Fehler ungebremst bis zum Nutzer.
Ein häufiges Missverständnis: noeviction verhindert nicht, dass bestehende Schlüssel mit abgelaufenem TTL entfernt werden. Der TTL-Mechanismus arbeitet unabhängig von der maxmemory-policy und löscht abgelaufene Schlüssel weiterhin lazy beim Zugriff und aktiv per Sampling. Nur die speicherdruckbasierte Verdrängung wird durch noeviction deaktiviert, nicht die reguläre Ablauflogik.
# noeviction konfigurieren und OOM-Fehler in der Anwendung behandeln
redis-cli CONFIG SET maxmemory-policy noeviction
redis-cli SET user:session:8842 "..."
# (error) OOM command not allowed when used memory > 'maxmemory'.
# Speicherreserve und Auslastung vor Erreichen des Limits prüfen
redis-cli INFO memory | grep -E "used_memory:|maxmemory:"
4. allkeys-lru und volatile-lru im Detail
LRU steht für Least Recently Used und verdrängt die Schlüssel, auf die am längsten nicht mehr zugegriffen wurde. Redis implementiert dabei kein exaktes LRU, sondern approximiertes LRU über Stichproben, weil eine vollständige LRU-Liste bei Millionen Schlüsseln zu viel Speicher-Overhead und CPU-Aufwand bedeuten würde. Diese maxmemory-policy zieht standardmäßig fünf zufällige Schlüssel, vergleicht deren Zugriffszeitstempel und entfernt den ältesten. Der Parameter maxmemory-samples steuert die Stichprobengröße und damit die Genauigkeit der Approximation.
Der Unterschied zwischen allkeys-lru und volatile-lru liegt ausschließlich im betrachteten Schlüsselbereich. allkeys-lru ist die verbreitetste maxmemory-policy für reine Cache-Deployments, weil jeder Schlüssel als potenzieller Verdrängungskandidat gilt und dadurch der gesamte Speicher effizient für heiße Daten genutzt wird. volatile-lru eignet sich hingegen für gemischte Instanzen, bei denen manche Schlüssel dauerhaft bestehen bleiben müssen und nur die Schlüssel mit TTL als Cache-Anteil behandelt werden.
# maxmemory-samples erhöhen für genauere LRU-Approximation
redis-cli CONFIG SET maxmemory-samples 10
# Aktuelle Policy und Sample-Größe prüfen
redis-cli CONFIG GET maxmemory-policy
# 1) "maxmemory-policy"
# 2) "allkeys-lru"
redis-cli CONFIG GET maxmemory-samples
# 1) "maxmemory-samples"
# 2) "10"
# Verdrängungsstatistik seit Serverstart
redis-cli INFO stats | grep evicted_keys
# evicted_keys:184213
5. allkeys-lfu und volatile-lfu: Häufigkeit statt Aktualität
LFU steht für Least Frequently Used und verdrängt Schlüssel nach Zugriffshäufigkeit statt nach Aktualität. Diese maxmemory-policy löst ein reales Problem von LRU: Ein Schlüssel, der über Wochen tausendfach pro Stunde gelesen wurde und dann für zehn Minuten nicht angefragt wird, würde unter reinem LRU trotzdem als Verdrängungskandidat gelten, obwohl er statistisch mit hoher Wahrscheinlichkeit bald wieder gebraucht wird. LFU vermeidet genau diese Fehleinschätzung, weil es die langfristige Zugriffshäufigkeit stärker gewichtet als den letzten Zeitpunkt.
Redis implementiert LFU über einen probabilistischen 8-Bit-Zähler pro Schlüssel, der im selben Speicherfeld gespeichert wird, das bei LRU den Zeitstempel enthält. Dieser Zähler erhöht sich bei jedem Zugriff logarithmisch statt linear, sodass auch extrem häufig gelesene Schlüssel nicht sofort den Maximalwert erreichen. Zusätzlich verringert sich der Zähler mit der Zeit über den konfigurierbaren lfu-decay-time, damit alte Popularität nicht unbegrenzt nachwirkt. Diese maxmemory-policy eignet sich besonders für Caches mit klarem Pareto-Muster, bei denen wenige Schlüssel den Großteil des Traffics ausmachen.
# redis.conf: LFU-Feintuning
maxmemory-policy allkeys-lfu
lfu-log-factor 10
lfu-decay-time 1
# Zugriffsfrequenz eines einzelnen Schlüssels auslesen (nur bei LFU-Policy gültig)
redis-cli OBJECT FREQ session:user:8842
# (integer) 217
# lfu-log-factor bestimmt, wie schnell der Zähler bei hoher Last sättigt
# Höherer Wert = feinere Auflösung bei sehr populären Schlüsseln
6. volatile-ttl und volatile-random
volatile-ttl verdrängt unter allen Schlüsseln mit gesetztem TTL zuerst diejenigen mit der kürzesten Restlebensdauer. Diese maxmemory-policy ist sinnvoll, wenn Schlüssel ohnehin bald ablaufen würden und ein vorzeitiges Entfernen kaum zusätzlichen Schaden anrichtet, etwa bei kurzlebigen Rate-Limiting-Countern oder Session-Tokens kurz vor Ablauf. Der Vorteil gegenüber LRU liegt darin, dass die Entscheidung deterministisch aus vorhandenen Metadaten getroffen wird, ohne zusätzliche Sampling-Kosten für Zugriffsmuster.
volatile-random und allkeys-random entfernen Schlüssel ohne jede Gewichtung nach Aktualität oder Häufigkeit. Das klingt zunächst nach der schlechtesten Wahl, ist aber in bestimmten Szenarien tatsächlich vertretbar: Wenn alle Schlüssel einer Instanz eine annähernd gleiche Zugriffswahrscheinlichkeit haben, etwa bei gleichmäßig verteiltem Zugriff auf ein großes, homogenes Dataset, bringt LRU oder LFU keinen messbaren Vorteil gegenüber Random, spart aber den CPU-Overhead der Sampling-Logik. Diese maxmemory-policy ist selten die erste Wahl, aber kein grundsätzlicher Fehler.
7. Die richtige maxmemory-policy für reine Caches
Für Redis-Instanzen, die ausschließlich als Cache vor einer Origin-Datenquelle laufen, ist allkeys-lru in den meisten Fällen der sinnvolle Standard, weil sie ohne Feinabstimmung gute Trefferraten liefert und die gesamte Kapazität für heiße Daten ausnutzt. Wo klare Popularitätsmuster vorliegen, etwa bei E-Commerce-Produktseiten, auf denen wenige Bestseller den Großteil der Anfragen erzeugen, liefert allkeys-lfu messbar bessere Trefferraten, weil sie diese ungleiche Verteilung besser erfasst als reine Aktualität.
Ein reiner Cache sollte grundsätzlich niemals noeviction verwenden, weil jeder Cache-Miss durch einen Fehler statt durch einen Fallback zur Origin-Quelle die schlechteste denkbare Ausfallart ist. Ebenso sollte für einen reinen Cache immer TTL auf allen Schlüsseln gesetzt werden, selbst wenn allkeys-Varianten der maxmemory-policy ohnehin unabhängig vom TTL verdrängen, weil TTLs verwaiste Daten unabhängig vom Speicherdruck aufräumen und die Datenkonsistenz mit der Origin-Quelle absichern.
8. maxmemory-policy für Primary Store und Mischbetrieb
Dient Redis als Primary Store, etwa für Sessions, Feature-Flags oder persistente Zähler, ist unkontrollierter Datenverlust durch Eviction ein ernstes Risiko. Hier ist noeviction in Kombination mit sorgfältiger Kapazitätsplanung und Monitoring der bevorzugte Ansatz. Alternativ, wenn ein Teil der Daten TTL-basiert ablaufen darf und ein anderer Teil dauerhaft bestehen muss, ist volatile-lru oder volatile-lfu die richtige maxmemory-policy, weil sie nur den TTL-behafteten Anteil als Verdrängungspuffer nutzt und den Rest garantiert unangetastet lässt.
In gemischten Deployments, in denen dieselbe Instanz sowohl Cache-Daten als auch geschäftskritische Zustände hält, ist eine klare Trennung nach TTL-Konvention die robusteste Lösung: Alle Cache-Schlüssel erhalten grundsätzlich ein TTL, alle Primary-Store-Schlüssel bleiben ohne Ablaufzeit, und die maxmemory-policy wird auf volatile-lru oder volatile-lfu gesetzt. So verdrängt Redis ausschließlich den Cache-Anteil und lässt kritische Daten unangetastet, selbst unter Speicherdruck.
| maxmemory-policy | Schlüsselbereich | Kriterium | Typischer Einsatz |
|---|---|---|---|
| noeviction | keiner | keine Verdrängung | Primary Store, kritische Zustände |
| allkeys-lru | alle Schlüssel | am längsten nicht genutzt | reiner Cache, Standardfall |
| volatile-lru | nur TTL-Schlüssel | am längsten nicht genutzt | Mischbetrieb Cache + Primary |
| allkeys-lfu | alle Schlüssel | am seltensten genutzt | Cache mit Pareto-Verteilung |
| volatile-ttl | nur TTL-Schlüssel | kürzeste Restlebensdauer | kurzlebige Tokens, Rate Limits |
9. Monitoring, Benchmarking und Umschalten im Betrieb
Die maxmemory-policy kann jederzeit im laufenden Betrieb per CONFIG SET geändert werden, ohne Redis neu zu starten. Die Änderung wirkt sofort auf zukünftige Verdrängungsentscheidungen, verändert aber nichts an bereits gespeicherten Daten. Vor jeder Umstellung sollte INFO memory und INFO stats als Baseline erfasst werden, insbesondere die Felder used_memory, evicted_keys und keyspace_hits im Verhältnis zu keyspace_misses, um die Trefferrate vor und nach dem Wechsel objektiv zu vergleichen.
Für einen belastbaren Vergleich zwischen zwei maxmemory-policy-Kandidaten empfiehlt sich ein kontrollierter A/B-Test unter realistischer Last, weil synthetische Benchmarks selten dieselbe Zugriffsverteilung wie Produktionstraffic erzeugen. redis-cli --latency-history zeigt, ob eine Policy zu spürbaren Latenzspitzen führt, während evicted_keys pro Minute die tatsächliche Verdrängungsrate offenlegt. Wer regelmäßig hohe Evictions bei niedriger Trefferrate beobachtet, sollte entweder die Speichergrenze anheben oder die maxmemory-policy wechseln, statt das Symptom zu ignorieren.
# Policy live umstellen ohne Neustart
redis-cli CONFIG SET maxmemory-policy allkeys-lfu
# Trefferrate berechnen
redis-cli INFO stats | grep -E "keyspace_hits|keyspace_misses"
# keyspace_hits:9821223
# keyspace_misses:412887
# Latenz-Spitzen während Eviction-Phasen beobachten
redis-cli --latency-history -i 5
# Persistente Änderung in redis.conf übernehmen (CONFIG SET wirkt nicht dauerhaft)
redis-cli CONFIG REWRITE
Mironsoft
Redis-Betrieb, Caching-Architektur und Performance-Tuning
Die falsche maxmemory-policy kostet Trefferrate oder Daten?
Wir analysieren eure Redis-Workloads, messen Zugriffsmuster und wählen gemeinsam die passende maxmemory-policy für Cache- und Primary-Store-Instanzen, mit Monitoring, das Fehlentscheidungen frühzeitig sichtbar macht.
Workload-Analyse
Zugriffsmuster und Verteilung ermitteln, bevor eine Policy gewählt wird
Konfiguration
maxmemory-policy, Samples und lfu-decay-time produktionsreif einstellen
Monitoring
Trefferrate, Evictions und Latenz dauerhaft im Blick behalten
10. Zusammenfassung
Die maxmemory-policy entscheidet, was mit Daten passiert, sobald Redis an sein Speicherlimit stößt, und ist deshalb eine der wichtigsten Betriebsentscheidungen überhaupt. noeviction schützt kritische Daten um den Preis von Schreibfehlern bei vollem Speicher. allkeys-lru und allkeys-lfu maximieren die Trefferrate reiner Caches, wobei LFU bei ungleicher Popularitätsverteilung im Vorteil ist. volatile-Varianten der maxmemory-policy ermöglichen Mischbetrieb, indem nur TTL-behaftete Schlüssel als Verdrängungspuffer dienen.
Die richtige Wahl ergibt sich nicht aus Bauchgefühl, sondern aus der Rolle der Redis-Instanz: reiner Cache, Primary Store oder Mischbetrieb. Monitoring von evicted_keys, Trefferrate und Latenz vor und nach jeder Umstellung liefert die Datenbasis, um die maxmemory-policy objektiv zu bewerten, statt sich auf Annahmen zu verlassen. Da die Policy jederzeit ohne Neustart wechselbar ist, lohnt sich kontrolliertes Experimentieren in der Produktion mehr als reine Theorie.
maxmemory-Policies im Vergleich: Das Wichtigste auf einen Blick
Für reine Caches
allkeys-lru als solider Standard, allkeys-lfu bei klarer Popularitätsverteilung mit wenigen Bestsellern.
Für Primary Store
noeviction mit Kapazitätsplanung, oder volatile-lru, wenn nur ein Teil der Daten Cache-Charakter hat.
Live umstellbar
CONFIG SET maxmemory-policy wirkt sofort, CONFIG REWRITE für dauerhafte Übernahme in redis.conf.
Monitoring-Felder
evicted_keys, keyspace_hits und keyspace_misses vor und nach jeder Umstellung vergleichen.