Fire-and-Forget ohne Warteschlangen-Overhead
Redis Pub/Sub verteilt Nachrichten in Echtzeit an alle aktuell verbundenen Abonnenten, ohne sie zu speichern oder eine Zustellgarantie zu geben. Diese Fire-and-Forget-Semantik macht Pub/Sub ideal fuer Live-Benachrichtigungen zwischen Services, aber ungeeignet fuer alles, was Persistenz oder garantierte Zustellung braucht.
Inhaltsverzeichnis
- 1. Was Redis Pub/Sub grundsaetzlich leistet
- 2. PUBLISH und SUBSCRIBE im Detail
- 3. PSUBSCRIBE: Pattern-basiertes Abonnieren
- 4. Pub/Sub in PHP mit Predis implementieren
- 5. Fire-and-Forget-Semantik verstehen
- 6. Praktische Anwendungsfaelle fuer Echtzeit-Events
- 7. Grenzen: keine Persistenz, kein Replay
- 8. Pub/Sub in geclusterten Redis-Umgebungen
- 9. Pub/Sub im Vergleich zu Streams und Queues
- 10. Zusammenfassung
- 11. FAQ
1. Was Redis Pub/Sub grundsaetzlich leistet
Redis Pub/Sub implementiert das klassische Publish-Subscribe-Muster: Ein Publisher sendet eine Nachricht an einen benannten Kanal, und alle Clients, die diesen Kanal zum Sendezeitpunkt abonniert haben, erhalten die Nachricht sofort. Anders als bei Listen oder Streams speichert Redis die Nachricht dabei nicht. Sie existiert nur für den Bruchteil einer Sekunde, in dem sie vom Publisher zu den aktuell verbundenen Subscribern übertragen wird, danach ist sie unwiederbringlich verschwunden.
Diese radikale Einfachheit ist zugleich die größte Stärke und die größte Einschränkung von Pub/Sub. Es gibt keine Warteschlange, keine Bestätigung, keine Wiederholungslogik. Ein Subscriber, der zum Zeitpunkt der Veröffentlichung nicht verbunden ist, verpasst die Nachricht endgültig. Diese Eigenschaft macht Pub/Sub zum idealen Werkzeug für echte Echtzeit-Events, bei denen nur der aktuelle Zustand zählt, aber zur denkbar schlechtesten Wahl für alles, was zuverlässige Zustellung erfordert.
2. PUBLISH und SUBSCRIBE im Detail
Das Grundmuster von Redis Pub/Sub besteht aus zwei Befehlen. SUBSCRIBE channel registriert einen Client als Abonnent eines bestimmten Kanals und blockiert die Verbindung anschließend, um eingehende Nachrichten entgegenzunehmen. PUBLISH channel message sendet eine Nachricht an alle aktuell verbundenen Abonnenten dieses Kanals und gibt die Anzahl der Empfänger zurück, ein nützlicher Indikator dafür, ob überhaupt jemand zugehört hat.
Wichtig ist, dass eine Redis-Verbindung im Subscribe-Modus für nahezu alle anderen Befehle blockiert ist. Ein Client, der SUBSCRIBE aufgerufen hat, kann in derselben Verbindung keine GET- oder SET-Operationen mehr ausführen, bis er sich mit UNSUBSCRIBE wieder abmeldet. In der Praxis bedeutet das: Anwendungen, die sowohl normale Redis-Operationen als auch Pub/Sub nutzen, benötigen dafür zwei getrennte Verbindungen.
# Terminal 1: Kanal abonnieren und blockierend auf Nachrichten warten
redis-cli SUBSCRIBE orders:updates
# Reading messages... (press Ctrl-C to quit)
# 1) "subscribe"
# 2) "orders:updates"
# 3) (integer) 1
# Terminal 2: Nachricht veroeffentlichen
redis-cli PUBLISH orders:updates '{"orderId":8842,"status":"shipped"}'
# (integer) 1 -- ein Abonnent hat die Nachricht empfangen
# In Terminal 1 erscheint sofort:
# 1) "message"
# 2) "orders:updates"
# 3) "{\"orderId\":8842,\"status\":\"shipped\"}"
3. PSUBSCRIBE: Pattern-basiertes Abonnieren
Neben dem exakten Kanalnamen unterstützt Redis mit PSUBSCRIBE pattern auch Pattern-basiertes Abonnieren über Glob-Style-Wildcards. Ein Abonnement auf orders:* empfängt Nachrichten von allen Kanälen, die mit orders: beginnen, etwa orders:updates, orders:cancelled oder orders:8842:status. Das ist besonders nützlich, wenn Kanalnamen dynamisch aus IDs zusammengesetzt werden, etwa pro Nutzer oder pro Bestellung, und ein zentraler Dienst alle Events unabhängig von der konkreten ID beobachten muss.
Der Preis der Flexibilität ist Performance: Pattern-Matching ist rechenintensiver als der exakte Abgleich bei SUBSCRIBE, weil Redis bei jeder PUBLISH-Operation alle registrierten Patterns gegen den veröffentlichten Kanalnamen prüfen muss, nicht nur einen Hash-Lookup durchführt. Bei einer sehr hohen Anzahl aktiver Pattern-Abonnements kann dieser Overhead spürbar werden, weshalb PSUBSCRIBE gezielt und nicht als Standardlösung für jeden Anwendungsfall eingesetzt werden sollte.
# Alle Order-bezogenen Kanaele auf einmal abonnieren
redis-cli PSUBSCRIBE "orders:*"
# 1) "psubscribe"
# 2) "orders:*"
# 3) (integer) 1
# Veroeffentlichung auf einem spezifischen Kanal
redis-cli PUBLISH orders:8842:status '{"status":"delivered"}'
# Empfangene Nachricht zeigt zusaetzlich das Match-Pattern:
# 1) "pmessage"
# 2) "orders:*"
# 3) "orders:8842:status"
# 4) "{\"status\":\"delivered\"}"
4. Pub/Sub in PHP mit Predis implementieren
In PHP verwendet Predis für Pub/Sub eine dedizierte, blockierende API, die sich vom sonstigen Request-Response-Muster von Redis-Befehlen unterscheidet. Der Subscriber-Client öffnet eine dauerhafte Verbindung und ruft für jede eingehende Nachricht einen Callback auf, was in der Regel in einem langlebigen Worker-Prozess läuft, nicht in einem klassischen kurzlebigen Webrequest.
Der Publisher hingegen ist ein normaler, kurzlebiger Aufruf, der problemlos aus einem Controller oder Service innerhalb eines Webrequests erfolgen kann, da PUBLISH nicht blockiert und sofort zurückkehrt.
<?php
declare(strict_types=1);
// Publisher: fires an event when an order status changes
final class OrderEventPublisher
{
public function __construct(private readonly \Predis\Client $redis)
{
}
/**
* Publish an order status change as a real-time event.
*/
public function publishStatusChange(int $orderId, string $status): void
{
$payload = json_encode(['orderId' => $orderId, 'status' => $status]);
$this->redis->publish('orders:updates', $payload);
}
}
// Subscriber: long-running worker process
final class OrderEventSubscriber
{
public function __construct(private readonly \Predis\Client $redis)
{
}
/**
* Block and react to incoming order update events.
*/
public function listen(): void
{
$pubsub = $this->redis->pubSubLoop();
$pubsub->subscribe('orders:updates');
foreach ($pubsub as $message) {
if ($message->kind === 'message') {
$event = json_decode($message->payload, true);
echo "Order {$event['orderId']} changed to {$event['status']}\n";
// Forward to WebSocket clients, trigger notifications, etc.
}
}
}
}
5. Fire-and-Forget-Semantik verstehen
Der Begriff Fire-and-Forget beschreibt exakt, was PUBLISH tut: Die Nachricht wird gesendet, und der Publisher kümmert sich nicht darum, ob und wie sie ankommt. Es gibt keine Bestätigung eines einzelnen Empfängers, nur die Gesamtzahl der Kanäle, an die die Nachricht ausgeliefert wurde. Diese Zahl sagt nichts darüber aus, ob die Nachricht tatsächlich verarbeitet wurde, nur dass sie den Netzwerk-Layer der Subscriber-Verbindung erreicht hat.
In der Praxis bedeutet Fire-and-Forget: Wenn ein Subscriber-Prozess während der Verarbeitung abstürzt, ist die Nachricht verloren, ohne dass irgendein anderer Teil des Systems davon erfährt. Es gibt keinen automatischen Retry-Mechanismus, keine Dead-Letter-Queue, keine Möglichkeit, verpasste Nachrichten nachträglich abzurufen. Anwendungen, die diese Semantik nutzen, müssen bewusst akzeptieren, dass gelegentlicher Nachrichtenverlust ein normaler, erwarteter Betriebszustand ist, keine Ausnahme.
6. Praktische Anwendungsfaelle fuer Echtzeit-Events
Redis Pub/Sub eignet sich hervorragend für Anwendungsfälle, bei denen nur der aktuellste Zustand zählt und ein verpasstes Event durch den nächsten Zustandsupdate ohnehin überholt wird. Live-Chat-Systeme sind ein klassisches Beispiel: Wenn eine Nachricht verloren geht, weil ein Client kurzzeitig nicht verbunden war, zeigt der nächste Verbindungsaufbau typischerweise den aktuellen Chat-Verlauf über eine separate, persistente Datenquelle an, Pub/Sub liefert nur die Echtzeit-Ergänzung für bereits verbundene Clients.
Weitere bewährte Anwendungsfälle sind Live-Dashboards mit sich ständig aktualisierenden Metriken, Präsenz-Indikatoren wie "Nutzer X ist gerade online", Cache-Invalidierung über mehrere Anwendungsinstanzen hinweg, bei der ein zentraler Publisher alle Instanzen über geänderte Schlüssel informiert, und Multiplayer-Spielzustände, bei denen jeder verpasste Frame durch den nächsten ohnehin ersetzt wird. Das gemeinsame Merkmal all dieser Fälle: Der Wert einer einzelnen Nachricht verfällt fast augenblicklich.
# Cache-Invalidierung ueber mehrere Anwendungsinstanzen per Pub/Sub
redis-cli SUBSCRIBE cache:invalidate
# Zentraler Publisher informiert alle Instanzen ueber einen geaenderten Schluessel
redis-cli PUBLISH cache:invalidate "product:4711"
# Jede Instanz loescht daraufhin lokal ihren In-Process-Cache fuer diesen Key
7. Grenzen: keine Persistenz, kein Replay
Die zentrale Einschränkung von Redis Pub/Sub ist das vollständige Fehlen von Persistenz. Anders als bei Redis Streams oder einer klassischen Message Queue existiert keine Möglichkeit, vergangene Nachrichten abzurufen, egal wie kurz der Client offline war. Ein Neustart eines Subscriber-Prozesses, selbst wenn er nur wenige Millisekunden dauert, bedeutet den unwiederbringlichen Verlust aller Nachrichten, die in dieser Zeit veröffentlicht wurden.
Diese Grenze macht Pub/Sub ungeeignet für alles, was auf Vollständigkeit angewiesen ist: Finanztransaktionen, Bestellbestätigungen, Audit-Logs oder jede Art von Event, dessen Verlust einen inkonsistenten Systemzustand nach sich zieht. Für solche Fälle sind Redis Streams mit ihrer Konsumenten-Gruppen-Logik und persistenten Nachrichten-IDs die richtige Wahl, oder eine dedizierte Message Queue wie RabbitMQ, die für genau dieses Problem entwickelt wurde.
8. Pub/Sub in geclusterten Redis-Umgebungen
In einem Redis Cluster wird eine Nachricht standardmäßig an alle Knoten im Cluster propagiert, damit Abonnenten unabhängig davon, mit welchem Knoten sie verbunden sind, alle Nachrichten erhalten. Dieses Verhalten funktioniert zuverlässig, erzeugt aber zusätzlichen Netzwerk-Traffic zwischen den Knoten, der bei sehr hoher Nachrichtenfrequenz zum Engpass werden kann. Seit Redis 7 existiert mit SSUBSCRIBE und SPUBLISH eine sogenannte Sharded-Pub/Sub-Variante, bei der Nachrichten nur innerhalb des für den jeweiligen Kanal-Hash-Slot zuständigen Shards verteilt werden.
Sharded Pub/Sub reduziert den Cluster-weiten Broadcast-Overhead erheblich und ist die empfohlene Wahl für Cluster-Deployments mit hoher Event-Frequenz. Der Unterschied zur Anwendung ist minimal: Statt SUBSCRIBE und PUBLISH werden lediglich SSUBSCRIBE und SPUBLISH verwendet, das Verhalten für den einzelnen Client bleibt identisch, nur die interne Verteilung im Cluster ändert sich.
# Sharded Pub/Sub seit Redis 7: reduziert Cluster-Broadcast
redis-cli SSUBSCRIBE orders:updates
redis-cli SPUBLISH orders:updates '{"orderId":8842,"status":"shipped"}'
# Anzahl aktiver Pub/Sub-Kanaele pruefen
redis-cli PUBSUB CHANNELS "orders:*"
# Anzahl Abonnenten pro Kanal ermitteln
redis-cli PUBSUB NUMSUB orders:updates
9. Pub/Sub im Vergleich zu Streams und Queues
Die Wahl zwischen Pub/Sub, Streams und dedizierten Message Queues haengt vollstaendig davon ab, ob Persistenz und garantierte Zustellung benoetigt werden oder ob reine Echtzeit-Verteilung ausreicht.
| Eigenschaft | Pub/Sub | Redis Streams |
|---|---|---|
| Persistenz | Keine, Nachricht verfaellt sofort | Ja, Nachrichten bleiben im Stream |
| Replay | Nicht moeglich | Ja, per Nachrichten-ID |
| Zustellgarantie | Keine, nur verbundene Clients | Ja, mit Consumer Groups und ACK |
| Latenz | Minimal, direkte Zustellung | Sehr niedrig, minimal hoeher als Pub/Sub |
| Typischer Einsatz | Live-Dashboards, Praesenz, Chat-Ergaenzung | Event-Sourcing, Task-Queues mit Historie |
Wer garantierte Zustellung, Replay-Faehigkeit oder Nachrichten-Historie braucht, sollte auf Redis Streams oder eine dedizierte Message Queue ausweichen. Pub/Sub bleibt die richtige Wahl, wenn ausschliesslich der aktuelle Moment zaehlt und der Implementierungsaufwand minimal bleiben soll.
Mironsoft
Redis-Architektur, Echtzeit-Kommunikation und Microservices
Echtzeit-Events zwischen euren Services aufbauen?
Wir entwerfen Event-Architekturen mit Redis Pub/Sub oder Streams, je nach Anforderung an Persistenz und Zustellgarantie, und integrieren sie sauber in eure bestehende Service-Landschaft.
Architektur-Design
Pub/Sub, Streams oder Message Queue passend zum Anwendungsfall auswaehlen
Implementierung
Publisher und Subscriber-Worker robust in PHP und weiteren Sprachen umsetzen
Skalierung
Sharded Pub/Sub und Cluster-Konfiguration fuer hohe Event-Frequenz
10. Zusammenfassung
Redis Pub/Sub mit PUBLISH, SUBSCRIBE und PSUBSCRIBE liefert Echtzeit-Events an alle aktuell verbundenen Abonnenten, ohne Nachrichten zu speichern oder eine Zustellgarantie zu geben. Diese Fire-and-Forget-Semantik ist ideal für Live-Dashboards, Präsenz-Indikatoren, Chat-Ergänzungen und Cache-Invalidierung über mehrere Instanzen, bei denen der Wert einer einzelnen Nachricht fast augenblicklich verfällt und ein Verlust unkritisch ist.
Für alles, was Persistenz, Replay oder garantierte Zustellung benötigt, ist Pub/Sub die falsche Wahl, hier sind Redis Streams mit Consumer Groups oder eine dedizierte Message Queue die richtige Antwort. Seit Redis 7 reduziert Sharded Pub/Sub über SSUBSCRIBE und SPUBLISH zusätzlich den Cluster-weiten Broadcast-Overhead bei hoher Event-Frequenz.
Pub/Sub für Echtzeit-Events, das Wichtigste auf einen Blick
Grundmuster
PUBLISH sendet, SUBSCRIBE empfaengt exakte Kanaele, PSUBSCRIBE erlaubt Pattern-basiertes Abonnieren.
Fire-and-Forget
Keine Bestaetigung, keine Warteschlange. Verpasste Nachrichten sind unwiederbringlich verloren.
Ideale Anwendungsfaelle
Live-Dashboards, Praesenz-Indikatoren, Cache-Invalidierung, Multiplayer-Zustaende.
Grenzen
Keine Persistenz, kein Replay. Fuer garantierte Zustellung Streams oder Message Queue nutzen.