Oder: Warum “nimm einfach Redis” nicht immer die Antwort ist
“Wir skalieren auf mehrere Server. Sollen wir auf Redis Sessions umsteigen?”
Diese Frage habe ich dutzende Male gehört. Die Antwort ist fast immer “kommt drauf an”—aber nicht auf die frustrierende, unverbindliche Art. Es gibt klare Kriterien, und wenn du die kennst, ist die Wahl einfach.
Die vier Optionen
Permalink to "Die vier Optionen"Symfony bringt vier Session Handler von Haus aus mit:
| Handler | Speicher | Skalierung | Persistenz |
|---|---|---|---|
| NativeFileSessionHandler | Lokales Dateisystem | Einzelner Server | Überlebt Neustarts |
| PdoSessionHandler | Datenbank (MySQL, PostgreSQL) | Multi-Server | Überlebt Neustarts |
| MemcachedSessionHandler | Memcached Server | Multi-Server | Verloren bei Neustart |
| RedisSessionHandler | Redis Server | Multi-Server | Konfigurierbar |
Jeder hat seine Vor- und Nachteile.
Datei Sessions: Der zuverlässige Standard
Permalink to "Datei Sessions: Der zuverlässige Standard"# config/packages/framework.yaml
framework:
session:
handler_id: null # Nutzt PHPs Standard-Datei-Handler
save_path: "%kernel.project_dir%/var/sessions/%kernel.environment%"
Geeignet für:
- Single-Server-Deployments
- Entwicklungsumgebungen
- Anwendungen, bei denen Einfachheit wichtiger ist als Skalierung
Vorteile:
- Keine Konfiguration nötig
- Kampferprobte Zuverlässigkeit
- Eingebautes Session Locking (keine Race Conditions)
- Überlebt Server-Neustarts
Nachteile:
- Sessions können nicht über mehrere App-Server geteilt werden
- Dateisystem-I/O kann zum Flaschenhals werden
- Session-Dateien sammeln sich an (braucht Garbage Collection)
Produktions-Tipp: Wenn du auf einem einzelnen Server bist und er die Last bewältigt, sind Datei-Sessions völlig in Ordnung. Kein Overkill nötig.
Datenbank Sessions: ACID-Garantien
Permalink to "Datenbank Sessions: ACID-Garantien"# config/packages/framework.yaml
framework:
session:
handler_id: Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler
// config/services.yaml
services:
Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler:
arguments:
- '%env(DATABASE_URL)%'
- lock_mode: 1 # LOCK_ADVISORY
Geeignet für:
- Multi-Server-Deployments, wenn du bereits eine Datenbank hast
- Anwendungen, die transaktionale Konsistenz erfordern
- Wenn Session-Daten Infrastrukturänderungen überleben müssen
Vorteile:
- Funktioniert über mehrere App-Server
- ACID-Garantien (Sessions werden nicht korrupt)
- Konfigurierbare Locking-Modi
- Sessions überleben Neustarts und Deployments
Nachteile:
- Erhöht Datenbank-Last
- Lock-Konflikte bei vielen parallelen Requests
- Langsamer als In-Memory-Lösungen
Lock-Modi erklärt
Permalink to "Lock-Modi erklärt"PdoSessionHandler bietet drei Lock-Modi:
use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler;
// Kein Locking - am schnellsten, aber Race Conditions möglich
PdoSessionHandler::LOCK_NONE
// Advisory Locking - ausgewogener Ansatz
PdoSessionHandler::LOCK_ADVISORY
// Transaktionales Locking - am sichersten, aber am langsamsten
PdoSessionHandler::LOCK_TRANSACTIONAL
Meine Empfehlung: Starte mit LOCK_ADVISORY. Geh nur auf LOCK_NONE
runter, wenn du profiliert und bestätigt hast, dass es ein Flaschenhals ist—und
du die Race-Condition-Risiken verstehst.
Redis Sessions: Die skalierbare Wahl
Permalink to "Redis Sessions: Die skalierbare Wahl"# config/packages/framework.yaml
framework:
session:
handler_id: Symfony\Component\HttpFoundation\Session\Storage\Handler\RedisSessionHandler
// config/services.yaml
services:
Redis:
class: Redis
calls:
- connect: ['%env(REDIS_HOST)%', '%env(int:REDIS_PORT)%']
Symfony\Component\HttpFoundation\Session\Storage\Handler\RedisSessionHandler:
arguments:
- '@Redis'
Geeignet für:
- High-Traffic-Anwendungen
- Horizontale Skalierung mit mehreren App-Servern
- Wenn du Sub-Millisekunden-Session-Reads brauchst
Vorteile:
- Extrem schnell (In-Memory)
- Skaliert horizontal
- Kann auf Disk persistieren (RDB/AOF)
- Unterstützt Clustering
Nachteile:
- Kein natives Session Locking (das ist ein großes Problem)
- Zusätzliche Infrastruktur zu warten
- Speicherkosten bei großen Session-Daten
Das Locking-Problem
Permalink to "Das Locking-Problem"Das verdient einen eigenen Artikel (kommt als nächstes), aber hier die Zusammenfassung:
Redis hat kein Session Locking. Es kann zu Race Conditions kommen, wenn du auf Sessions zugreifst. Zum Beispiel “Invalid CSRF token”-Fehler. — Symfony Dokumentation
Wenn deine App parallele AJAX-Requests macht, die Session-Daten ändern, können Redis Sessions kaputtgehen. Das Symptom: zufällige Logouts, verlorene Flash-Messages, CSRF-Fehler.
Workarounds:
- Locking selbst in der App bauen
session_write_close()früh aufrufen- Einen Redis Session Handler mit Locking nutzen (z.B.
snc/redis-bundle)
Memcached Sessions: Einfaches Caching
Permalink to "Memcached Sessions: Einfaches Caching"# config/packages/framework.yaml
framework:
session:
handler_id: Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcachedSessionHandler
// config/services.yaml
services:
Memcached:
class: Memcached
calls:
- addServer: ['%env(MEMCACHED_HOST)%', '%env(int:MEMCACHED_PORT)%']
Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcachedSessionHandler:
arguments:
- '@Memcached'
Geeignet für:
- Einfache verteilte Caching-Anforderungen
- Wenn du bereits Memcached für anderes Caching hast
- Anwendungen, bei denen Session-Verlust verkraftbar ist
Vorteile:
- Schnell (In-Memory)
- Einfaches Protokoll
- Funktioniert über mehrere Server
Nachteile:
- Keine Persistenz (Sessions bei Neustart verloren)
- Kein natives Locking (gleiche Race-Condition-Probleme wie Redis)
- LRU-Eviction kann Sessions zufällig löschen bei Speicherdruck
Meine Meinung: Wenn du nicht bereits Memcached in deinem Stack hast, bevorzuge Redis. Es macht alles was Memcached macht, plus Persistenz und mehr Datenstrukturen.
Die Entscheidungsmatrix
Permalink to "Die Entscheidungsmatrix"| Anforderung | Beste Wahl |
|---|---|
| Einzelner Server, einfache App | Dateien |
| Multi-Server, Zuverlässigkeit wichtig | Datenbank (PDO) |
| Multi-Server, Geschwindigkeit wichtig | Redis (mit Locking-Bewusstsein) |
| Bereits Memcached im Einsatz | Memcached (aber Redis in Betracht ziehen) |
| ACID-Garantien erforderlich | Datenbank (PDO) |
| Sub-Millisekunden-Reads | Redis oder Memcached |
| Session-Daten müssen Neustarts überleben | Dateien, Datenbank oder Redis mit Persistenz |
Zwischen Handlern migrieren
Permalink to "Zwischen Handlern migrieren"Beim Wechsel des Session Handlers werden normalerweise alle ausgeloggt. Symfonys
MigratingSessionHandler löst das:
use Symfony\Component\HttpFoundation\Session\Storage\Handler\MigratingSessionHandler;
use Symfony\Component\HttpFoundation\Session\Storage\Handler\RedisSessionHandler;
use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler;
// Liest vom alten Handler, schreibt in beide
$handler = new MigratingSessionHandler(
new PdoSessionHandler($pdo), // Alter Handler (liest zuerst von hier)
new RedisSessionHandler($redis) // Neuer Handler (Schreibvorgänge gehen an beide)
);
Lass das für eine Session-Lifetime laufen (z.B. 24 Stunden), dann wechsle zu Redis-only:
$handler = new RedisSessionHandler($redis);
Zero-Downtime-Migration ohne jemanden auszuloggen.
Meine Empfehlungen
Permalink to "Meine Empfehlungen"Für die meisten Anwendungen
Permalink to "Für die meisten Anwendungen"Starte mit Datei Sessions. Wenn du nicht mehrere App-Server betreibst, brauchst du keinen verteilten Session-Speicher. Datei Sessions sind zuverlässig, schnell genug und haben ordentliches Locking.
Wenn du skalierst
Permalink to "Wenn du skalierst"Wechsle zuerst zu Datenbank Sessions. Du hast bereits eine Datenbank. Die zusätzliche Last ist normalerweise vernachlässigbar, und du bekommst ordentliches Locking. Wechsle nur zu Redis, wenn du gemessen und bestätigt hast, dass die Datenbank ein Flaschenhals ist.
Für High-Traffic-Anwendungen
Permalink to "Für High-Traffic-Anwendungen"Nutze Redis, aber:
- Verstehe die Locking-Einschränkungen
- Bau Schutzmaßnahmen ein (mehr dazu im nächsten Artikel)
- Konfiguriere Persistenz (mindestens RDB-Snapshots)
Der “beste” Session Handler hängt von deinen Rahmenbedingungen ab. Datei Sessions funktionieren für die meisten Anwendungen. Wenn du skalieren musst, sind Datenbank Sessions ein vernünftiger Mittelweg. Redis ist die richtige Wahl für High-Traffic-Apps—aber nur wenn du das Locking-Problem handhabst.
Als nächstes: Redis Session Locking Fallstricke—die Race Conditions, die jeden überraschen.
