Sessions, Object Cache und Full Page Cache sauber trennen
Redis übernimmt in Magento gleich drei Rollen: Session-Speicher, Object-Cache-Backend und optional Full-Page-Cache. Wer alle drei Rollen in derselben Datenbank ablegt, riskiert Tag-Kollisionen, unnötige Cache-Flushes und im schlimmsten Fall abgemeldete Kunden durch verlorene Sessions. Dieser Artikel zeigt, wie Redis in Magento korrekt konfiguriert, überwacht und vor Speicherüberlauf geschützt wird.
Inhaltsverzeichnis
- 1. Warum Redis in Magento drei Rollen übernimmt
- 2. Redis für Session-Storage konfigurieren
- 3. Redis als Cache-Backend für den Object Cache
- 4. Redis als Full-Page-Cache-Backend
- 5. Cache-Tag-Invalidierung verstehen
- 6. Persistence-Strategien: RDB vs. AOF
- 7. Memory Eviction Policies richtig wählen
- 8. Redis-Hit-Rate überwachen
- 9. Häufige Magento-Redis-Fehlkonfigurationen
- 10. Zusammenfassung
- 11. FAQ
1. Warum Redis in Magento drei Rollen übernimmt
Redis übernimmt in einem Magento-Setup nicht eine, sondern drei unterschiedliche Rollen gleichzeitig: Session-Speicher, Cache-Backend für den Object Cache und optional Full-Page-Cache-Backend für den page_cache. Ohne Redis läuft der Object Cache standardmäßig über Cm_Cache_Backend_File und schreibt tausende kleine Dateien ins Dateisystem, was bei mehreren Application-Servern zu Inkonsistenzen führt, weil jeder Server einen eigenen lokalen Cache hält. Redis löst dieses Problem, indem alle Application-Server denselben zentralen Cache-Speicher nutzen und Invalidierungen sofort für alle Server sichtbar sind.
Die drei Rollen werden in env.php getrennt konfiguriert: der Block session, der Block cache mit dem Sub-Key frontend/default für den Object Cache, und optional der Block cache/frontend/page_cache für den Full-Page-Cache. Technisch können alle drei denselben Redis-Prozess nutzen, sollten dabei aber unterschiedliche logische Datenbanken über den database-Index verwenden. Diese Trennung ist keine Kosmetik, sondern verhindert Kollisionen bei Tag-basierten Invalidierungen und macht gezielte FLUSHDB-Operationen möglich, ohne aktive Kundensessions zu zerstören.
2. Redis für Session-Storage konfigurieren
Die Session-Konfiguration steht in env.php unter session mit save auf redis gesetzt. Neben host, port und database sind zwei Parameter entscheidend: session locking und bot_first_lifetime. Magento nutzt standardmäßig Session-Locking, damit parallele Requests derselben Session, etwa AJAX-Warenkorb-Updates, sich nicht gegenseitig überschreiben. Die Parameter bot_first_lifetime und bot_lifetime reduzieren die Wartezeit für Bot-Traffic, der ohnehin keine Schreibkonflikte erzeugt, und verhindern damit unnötiges Lock-Spinning bei Crawlern.
Der Parameter disable_locking sollte in Produktivumgebungen nie auf 1 stehen, außer die Anwendung ist nachweislich frei von parallelen Schreibzugriffen auf dieselbe Session, sonst entstehen Race Conditions beim Warenkorb. Die TTL der Session-Keys in Redis wird über session.gc_maxlifetime aus der php.ini abgeleitet, nicht über eine eigene Magento-Einstellung. Der große Vorteil gegenüber Dateisystem-Sessions: Mehrere Application-Server teilen sich denselben Session-Store, sodass ein Load Balancer ohne Sticky Sessions arbeiten kann und ein Server-Ausfall keine Nutzer mehr ausloggt.
<?php
// app/etc/env.php excerpt: separate Redis roles with distinct database indices
return [
'session' => [
'save' => 'redis',
'redis' => [
'host' => '127.0.0.1',
'port' => '6379',
'database' => '0',
'password' => '',
'timeout' => '2.5',
'persistent_identifier' => 'magento_session',
'bot_first_lifetime' => '60',
'bot_lifetime' => '7200',
'max_lifetime' => '2592000',
'min_lifetime' => '60',
'disable_locking' => '0',
'log_level' => '1',
],
],
'cache' => [
'frontend' => [
'default' => [
'backend' => 'Magento\Framework\Cache\Backend\RemoteSynchronizedCache',
'backend_options' => [
'server' => '127.0.0.1',
'port' => '6379',
'database' => '1',
'compress_data' => '1',
'compression_lib' => 'gzip',
'persistent' => 'magento_cache',
],
],
'page_cache' => [
'backend' => 'Magento\Framework\Cache\Backend\Redis',
'backend_options' => [
'server' => '127.0.0.1',
'port' => '6379',
'database' => '2',
'compress_data' => '1',
'compression_lib' => 'gzip',
'persistent' => 'magento_page_cache',
],
],
],
],
];
3. Redis als Cache-Backend für den Object Cache
Der Object Cache landet über cache/frontend/default/backend_options auf einen Redis-Backend-Typ. Wichtig ist ein eigener database-Index, der sich von Session und page_cache unterscheidet, im Beispiel oben database 1 statt 0. Der Parameter compress_data aktiviert Kompression für gecachte Werte und sollte auf 1 stehen: Layout-Caches und Konfigurationscaches enthalten viel redundanten, hochgradig komprimierbaren Text, sodass sich der Speicherverbrauch je nach Katalogumfang um 50 bis 70 Prozent reduzieren lässt. compression_lib steuert die Bibliothek, gzip ist der stabile Standard, lz4 oder zstd sind schneller bei etwas höherem CPU-Verbrauch.
Für den Verbindungsaufbau ist persistent entscheidend: Ohne diesen Parameter öffnet jeder PHP-FPM-Worker bei jedem Request eine neue TCP-Verbindung zu Redis, inklusive Handshake-Overhead. Mit einer gesetzten persistent-ID wird die Verbindung über Requests hinweg wiederverwendet, was besonders unter Last spürbar Latenz spart. Die Erweiterung phpredis übernimmt dabei das eigentliche Connection-Pooling auf PHP-Prozessebene, Credis dient nur als Fallback, wenn phpredis nicht installiert ist.
4. Redis als Full-Page-Cache-Backend
Für den Full-Page-Cache gibt es zwei grundsätzlich verschiedene Architekturen: Varnish als Reverse Proxy vor dem Webserver oder Redis als integriertes page_cache-Backend, das Magento selbst über PHP ausliefert. Varnish beantwortet Cache-Treffer, ohne dass überhaupt ein PHP-Prozess startet, und unterstützt Edge Side Includes, mit denen personalisierte Blöcke wie Mini-Cart oder Login-Status aus dem gecachten HTML ausgespart und separat nachgeladen werden. Das macht Varnish bei hohem Traffic praktisch konkurrenzlos schnell.
Redis als FPC-Backend ist einfacher zu betreiben, weil kein separater Reverse Proxy vor der Anwendung steht und SSL-Terminierung nicht zusätzlich konfiguriert werden muss. Der Nachteil: Jeder Request durchläuft trotzdem den PHP-Bootstrap-Prozess von Magento, bevor die gecachte HTML-Antwort aus Redis geladen und ausgeliefert wird, was spürbar langsamer ist als Varnishs Zero-PHP-Antwortpfad. Für kleinere und mittlere Shops ohne dedizierten Infrastruktur-Zugriff auf Varnish, für Staging-Umgebungen und für Setups hinter Managed-Hosting-Proxies ohne Varnish-Support ist Redis-FPC dennoch die pragmatischere Wahl.
5. Cache-Tag-Invalidierung verstehen
Jede cachefähige Entität in Magento wird beim Speichern mit Tags versehen, etwa cat_p_123 für ein Produkt oder cat_c_45 für eine Kategorie. Ändert sich ein Produkt, ruft Magento intern eine Invalidierung für genau diese Tags auf, nicht für den gesamten Cache. Der Befehl bin/magento cache:clean räumt über die TypeListInterface gezielt invalidierte Cache-Typen ab, während bin/magento cache:flush den kompletten Redis-Keyspace der jeweiligen Rolle per FLUSHDB leert, inklusive aller noch gültigen Einträge.
Der Redis-Cache-Backend von Magento implementiert die Tag-Zuordnung über zusätzliche Index-Keys im Format zc:ta:<tag>, die als Sets die zugehörigen Cache-Keys referenzieren. Beim Löschen eines Tags iteriert Redis über dieses Set und entfernt jeden referenzierten Key einzeln, was bei sehr großen Tag-Gruppen, etwa beim globalen Preis-Update, spürbar länger dauert als ein einfacher FLUSHDB. In der Praxis bedeutet das: Häufige, kleine Tag-Invalidierungen sind günstiger als seltene, große Batch-Invalidierungen über tausende Produkte gleichzeitig.
<?php
declare(strict_types=1);
namespace Mironsoft\CacheTools\Model;
use Magento\Framework\App\CacheInterface;
/**
* Cleans cache entries selectively by tag instead of flushing the whole store.
*/
class TagInvalidator
{
public function __construct(
private readonly CacheInterface $cache
) {
}
/**
* Invalidate only the cache entries tagged with the given product IDs.
*
* @param int[] $productIds
* @return void
*/
public function invalidateProducts(array $productIds): void
{
$tags = array_map(static fn (int $id): string => 'cat_p_' . $id, $productIds);
// Selective clean: only keys referenced by these tags are removed,
// the rest of the object cache stays warm.
$this->cache->clean(\Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG, $tags);
}
}
6. Persistence-Strategien: RDB vs. AOF
RDB-Snapshots schreiben in konfigurierbaren Intervallen, etwa save 900 1, save 300 10, save 60 10000, den kompletten Datenbestand als Binärdatei auf die Platte. Der Vorteil: kompakte Dateien, schneller Neustart, geringer Laufzeit-Overhead zwischen den Snapshots. Der Nachteil: Alle Schreibvorgänge seit dem letzten Snapshot gehen bei einem Absturz verloren. Für reine Cache-Rollen wie Object Cache und Full Page Cache ist das unkritisch, ein Cache-Miss nach einem Crash ist einfach eine Neuberechnung, kein Datenverlust.
Für die Session-Rolle ist das anders zu bewerten: Verlorene Sessions bedeuten für hunderte gleichzeitig aktive Kunden einen unfreiwilligen Logout und im schlimmsten Fall einen verlorenen Warenkorb. Hier lohnt sich Append-Only-File-Persistence mit appendonly yes und appendfsync everysec als Kompromiss zwischen Datensicherheit und I/O-Last. appendfsync always synchronisiert bei jedem Schreibbefehl und ist als Session-Store spürbar langsamer, ohne dass der zusätzliche Sicherheitsgewinn den Produktivbetrieb rechtfertigt. Für Cache- und FPC-Rollen ist Persistence oft komplett verzichtbar.
# redis.conf: durable persistence for the session role (database 0)
appendonly yes
appendfsync everysec
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
save 900 1
save 300 10
# redis.conf: cache and FPC roles do not need durability -
# a cache miss just costs one recomputation, not customer data
# (apply via a second instance or CONFIG SET per logical database use case)
save ""
appendonly no
7. Memory Eviction Policies richtig wählen
maxmemory definiert die harte Speichergrenze pro Redis-Instanz, maxmemory-policy bestimmt, was passiert, wenn diese Grenze erreicht ist. Die Standardeinstellung noeviction lehnt neue Schreibbefehle mit einem Fehler ab, sobald der Speicher voll ist. Für einen Magento-Cache bedeutet das im schlimmsten Fall Exceptions bei jedem Seitenaufruf, sobald die Grenze erreicht ist, statt eines stillen, unauffälligen Verhaltens.
Für Object Cache und Full Page Cache ist allkeys-lru die richtige Wahl: Redis entfernt bei Speicherdruck die am längsten nicht genutzten Keys, unabhängig davon, ob eine TTL gesetzt ist. Für den Session-Store ist volatile-lru vorzuziehen, weil dort ausschließlich Keys mit gesetzter TTL entfernt werden, was bei Magento-Sessions durchgängig der Fall ist. noeviction für den Session-Store ist ebenfalls vertretbar, solange maxmemory großzügig dimensioniert und aktiv überwacht wird. Der evicted_keys-Zähler in INFO stats zeigt sofort, ob eine Policy in der Praxis tatsächlich greift oder ob die Speichergrenze grundsätzlich zu knapp bemessen ist.
8. Redis-Hit-Rate überwachen
redis-cli INFO stats liefert die beiden zentralen Zähler keyspace_hits und keyspace_misses. Die Trefferquote berechnet sich als hits / (hits + misses) und sollte für den Object Cache im Dauerbetrieb deutlich über 90 Prozent liegen, da sich Konfiguration und Layout nur selten ändern. Kurzzeitige Einbrüche direkt nach einem Deployment oder einer Reindexierung sind normal, weil dabei gezielt Tags invalidiert werden und der Cache sich erst wieder aufbauen muss.
Für die laufende Beobachtung eignet sich redis-cli --stat, das im Sekundentakt Verbindungen, Speicherverbrauch, Hits und Evictions als Live-Tabelle ausgibt. redis-cli --bigkeys scannt den kompletten Keyspace und identifiziert ungewöhnlich große Einzel-Keys, ein häufiger Hinweis auf fehlende Kompression oder falsch dimensionierte Cache-Einträge. Für produktives Monitoring über die Zeit empfiehlt sich ein dedizierter redis_exporter für Prometheus mit Grafana-Dashboard, der Trefferquote, Speicherverbrauch und Eviction-Rate historisch nachvollziehbar macht und bei Grenzwertüberschreitungen automatisch alarmiert.
# Hit rate from raw counters
redis-cli -n 1 INFO stats | grep -E 'keyspace_(hits|misses)|evicted_keys'
# keyspace_hits:8452110
# keyspace_misses:214332
# evicted_keys:0
# Live overview: connections, memory, ops/sec, hits, evictions
redis-cli --stat
# Find oversized keys, common sign of missing compression
redis-cli -n 1 --bigkeys
# Current memory usage vs the configured hard limit
redis-cli INFO memory | grep -E 'used_memory_human|maxmemory_human|maxmemory_policy'
9. Häufige Magento-Redis-Fehlkonfigurationen
Der häufigste Fehler ist die gemeinsame Nutzung derselben Redis-Datenbank für Session, Object Cache und Full Page Cache. Ein FLUSHDB für den Cache löscht dann versehentlich auch alle aktiven Sessions, und eine Massen-Tag-Invalidierung für Produkte kann in seltenen Fällen mit Session-Keys kollidieren, wenn Prefixe nicht sauber getrennt sind. Die Lösung ist immer dieselbe: drei unterschiedliche database-Indizes, im Idealfall sogar drei getrennte Redis-Instanzen oder zumindest getrennte maxmemory-Grenzen pro logischer Datenbank.
Der zweitwichtigste Fehler ist eine fehlende oder falsche maxmemory-policy. Ohne explizite Konfiguration bleibt Redis bei noeviction, was bei vollem Speicher zu abgelehnten Schreibbefehlen und Exceptions im Shop führt, statt Cache-Einträge geordnet zu verdrängen. Fehlende Kompression, wenn compress_data nicht gesetzt ist, verschwendet bei großen Katalogen erheblich Speicher und beschleunigt damit genau das OOM-Risiko, das eine korrekte Eviction-Policy eigentlich abfedern soll. Fehlende persistente Verbindungen erzeugen unnötigen TCP-Handshake-Overhead auf jedem Request, und ein fehlender persistent-Identifier bei mehreren Magento-Instanzen auf demselben Redis führt zu Cache-Kollisionen zwischen Staging und Produktion.
# Quick diagnostic pass before deploying a new Magento environment
# 1. Check which eviction policy is actually active
redis-cli CONFIG GET maxmemory-policy
redis-cli CONFIG GET maxmemory
# 2. Verify roles are not sharing the same logical database
for i in 0 1 2; do
echo "db$i: $(redis-cli -n $i DBSIZE)"
done
# 3. Benchmark connection overhead with and without persistent connections
redis-benchmark -h 127.0.0.1 -p 6379 -n 100000 -q -t GET,SET
# 4. docker-compose.yaml: one Redis service, three isolated logical roles
# (or split into three services for full isolation under heavy load)
services:
redis:
image: redis:7-alpine
command: redis-server --maxmemory 512mb --maxmemory-policy allkeys-lru
ports:
- "6379:6379"
| Redis-Rolle | DB-Index | Falsche Konfiguration | Richtige Konfiguration |
|---|---|---|---|
| Sessions | 0 | allkeys-lru + geteilte DB mit Cache | volatile-lru, eigene DB, AOF everysec |
| Object Cache | 1 | noeviction ohne Monitoring | allkeys-lru, compress_data aktiv |
| Full Page Cache | 2 | gleiche DB wie Object Cache | allkeys-lru, eigene DB, save deaktiviert |
| Persistence-Wahl | - | appendfsync always überall | everysec als Standardkompromiss |
| Connection Handling | - | kein persistent-Parameter gesetzt | persistent-ID reduziert Handshake-Overhead |
In der Praxis hängen die drei Redis-Rollen eng zusammen: Eine falsch dimensionierte Eviction-Policy im Object Cache erhöht die Last auf die Datenbank, weil häufiger neu berechnet werden muss, was wiederum die Antwortzeiten und damit indirekt auch die Full-Page-Cache-Trefferquote beeinflusst. Wer die Trennung aus der Tabelle konsequent umsetzt und die Kennzahlen aus Abschnitt 8 im Blick behält, verhindert die meisten produktionsrelevanten Redis-Ausfälle, bevor sie überhaupt auftreten.
Mironsoft
Redis-Architektur, Cache-Tuning und Performance-Audits für Magento-Shops
Redis-Caching, das eurem Shop nicht um die Ohren fliegt?
Wir analysieren eure bestehende Redis-Konfiguration, trennen Session-, Cache- und FPC-Rollen sauber voneinander und setzen Eviction Policies, Persistence und Monitoring so auf, dass euer Shop auch unter Last stabil bleibt.
Redis-Audit
DB-Trennung, Eviction Policy und Persistence-Strategie prüfen und korrigieren
Cache-Tuning
Kompression, Connection Pooling und Tag-Invalidierung optimieren
Monitoring-Setup
Hit-Rate-Tracking mit Prometheus/Grafana und automatische Alerts
10. Zusammenfassung
Redis als Caching-Layer in Magento löst ein Kernproblem: Session-Storage, Object Cache und Full Page Cache haben unterschiedliche Anforderungen an Persistence, Eviction und Verfügbarkeit, teilen sich aber oft dieselbe Redis-Instanz. Getrennte database-Indizes, eine zur Rolle passende maxmemory-policy und eine bewusste Entscheidung zwischen RDB, AOF oder komplett ohne Persistence verhindern die häufigsten Produktionsausfälle. Kompression über compress_data und persistente Verbindungen reduzieren zusätzlich Speicherverbrauch und Latenz spürbar, ohne dass dafür zusätzliche Infrastruktur nötig wäre.
Der entscheidende Unterschied zwischen einem stabilen und einem fragilen Redis-Setup liegt selten in der Wahl des Tools selbst, sondern in der konsequenten Trennung der drei Rollen und im kontinuierlichen Monitoring von Trefferquote, Speicherverbrauch und Eviction-Rate. Wer INFO stats regelmäßig auswertet und Grenzwerte proaktiv überwacht, statt erst nach dem ersten OOM-Crash zu reagieren, hält Redis dauerhaft als verlässlichen, schnellen Caching-Layer im Griff.
Redis als Caching-Layer in Magento - Das Wichtigste auf einen Blick
Drei Rollen trennen
Session, Object Cache und Full Page Cache brauchen eigene database-Indizes, im Idealfall eigene Redis-Instanzen.
Eviction Policy je Rolle
allkeys-lru für reine Caches, volatile-lru für Sessions, niemals noeviction ohne Monitoring.
Persistence bewusst wählen
AOF everysec für Sessions, RDB oder keine Persistence für reine Cache-Rollen.
Hit-Rate überwachen
INFO stats regelmäßig prüfen, evicted_keys als Frühwarnsignal für zu knappes maxmemory.