Redis Messaging Showdown - Pub/Sub vs. Streams für ereignisgesteuerte Architekturen
James Reed
Infrastructure Engineer · Leapcell

Einleitung
In der dynamischen Landschaft moderner Softwarearchitektur sind ereignisgesteuerte Systeme zu einem Eckpfeiler für den Aufbau skalierbarer, robuster und reaktionsfähiger Anwendungen geworden. Im Herzen dieser Systeme liegt die effiziente Nachrichtenübermittlung, die es verschiedenen Komponenten ermöglicht, zu kommunizieren und auf Änderungen zu reagieren. Redis, bekannt für seine blitzschnelle Leistung und vielseitigen Datenstrukturen, bietet zwei überzeugende Optionen für das Message Brokering: Pub/Sub und Streams. Obwohl beide die Kommunikation erleichtern, bedienen sie grundlegend unterschiedliche Nachrichtenparadigmen – Pub/Sub für "Fire-and-Forget"-Übertragungen und Streams für persistente, geordnete Ereignisprotokolle. Das Verständnis ihrer Nuancen ist entscheidend für jeden Entwickler, der das volle Potenzial von Redis in ereignisgesteuerten Designs nutzen möchte. Dieser Artikel wird diese beiden Mechanismen zerlegen, ihre Prinzipien, Implementierungen und idealen Anwendungsfälle untersuchen und Sie befähigen, fundierte architektonische Entscheidungen zu treffen.
Die Messaging-Paradigmen von Redis
Bevor wir uns mit den Details befassen, wollen wir ein klares Verständnis der Kernkonzepte entwickeln, die unserer Diskussion zugrunde liegen.
Publisher-Subscriber (Pub/Sub)-Modell: Dies ist ein klassisches asynchrones Nachrichtenmuster, bei dem Sender (Publisher) Nachrichten nicht direkt an bestimmte Empfänger (Subscriber) senden. Stattdessen veröffentlichen sie Nachrichten in Kategorien oder Themen, ohne zu wissen, wer, falls überhaupt, zuhört. Subscriber bekunden Interesse an einer oder mehreren Kategorien und erhalten alle Nachrichten, die in diesen Kategorien veröffentlicht werden. Es ist ein Broadcast-Mechanismus.
Message Queue / Log: Eine Message Queue oder allgemeiner ein Message Log ist eine Form der asynchronen Service-to-Service-Kommunikation, die in Serverless- und Microservices-Architekturen verwendet wird. Nachrichten werden persistent in einer Warteschlange oder einem Protokoll gespeichert, bis sie von einem Konsumenten verarbeitet und gelöscht werden. Dies gewährleistet Zuverlässigkeit und ermöglicht es mehreren Konsumenten, Nachrichten zu verarbeiten, auch wenn Produzenten offline sind.
Nun wollen wir untersuchen, wie Redis diese Paradigmen implementiert.
Redis Pub/Sub: Der "Fire-and-Forget"-Broadcast
Redis Pub/Sub ist ein unkompliziertes In-Memory-Nachrichtensystem, das für Echtzeitbenachrichtigungen und Broadcasts entwickelt wurde.
Prinzip: Wenn ein Client eine Nachricht an einen channel PUBLISHed, leitet Redis diese Nachricht sofort an alle Clients weiter, die aktuell diesem channel SUBSCRIBEd sind.
Hauptmerkmale:
- "Fire-and-Forget": Nachrichten werden nicht persistent gespeichert. Wenn keine Clients zu einem Kanal abonniert sind, wenn eine Nachricht veröffentlicht wird, geht die Nachricht verloren.
- Entkoppelt: Publisher und Subscriber sind sich völlig unbekannt.
- Skalierbarkeit: Kann eine große Anzahl von Abonnenten und Nachrichtendurchsatz bewältigen, begrenzt nur durch die Netzwerkbandbreite und die Verarbeitungsgeschwindigkeit der Clients.
Implementierungsbeispiel:
Lassen Sie uns dies mit einfachen redis-cli-Befehlen veranschaulichen.
-
Subscriber 1:
redis-cli SUBSCRIBE chat_room_1Dieser Client wartet nun auf Nachrichten auf
chat_room_1. -
Subscriber 2 (in einem anderen Terminal):
redis-cli SUBSCRIBE chat_room_1Dieser Client abonniert ebenfalls denselben Kanal.
-
Publisher (in einem dritten Terminal):
redis-cli PUBLISH chat_room_1 "Hello everyone in chat_room_1!"Sowohl Subscriber 1 als auch Subscriber 2 erhalten sofort:
1) "message" 2) "chat_room_1" 3) "Hello everyone in chat_room_1!"Wenn sich ein Client nach dem
PUBLISH-Befehl abonniert, erhält er die Nachricht "Hello everyone..." nicht.
Anwendungsszenarien:
- Echtzeit-Chat-Anwendungen: Sofortige Zustellung von Nachrichten an Online-Benutzer.
- Live-Anzeigetafeln/Feeds: Push-Updates an aktive Benutzer.
- Cache-Invalidierung: Benachrichtigung von Anwendungsinstanzen zur Aktualisierung ihrer lokalen Caches, wenn sich zugrunde liegende Daten ändern.
- Ereignisbenachrichtigungen: Senden sofortiger Warnungen (z. B. "neue Bestellung aufgegeben") an interessierte Dienste für die transiente Verarbeitung.
Redis Streams: Das persistente, geordnete Ereignisprotokoll
Redis Streams, eingeführt in Redis 5.0, bieten eine robustere und dauerhaftere Messaging-Lösung, die als Append-Only-Log fungiert.
Prinzip: Nachrichten (Einträge) werden in geordneter Weise am Ende eines Streams hinzugefügt, jeder mit einer eindeutigen ID versehen. Konsumenten können von jedem Punkt im Stream lesen und ihren Lesefortschritt steuern.
Hauptmerkmale:
- Persistenz: Nachrichten werden im Stream gespeichert, bis sie explizit entfernt oder gekürzt werden, was sie dauerhaft macht.
- Geordnet: Einträge sind durch ihre Entry-ID garantiert geordnet.
- Mehrere Konsumenten/Konsumentengruppen: Ermöglicht mehreren unabhängigen Konsumenten die Verarbeitung derselben Nachrichten und Konsumentengruppen die Koordinierung der Verarbeitung zwischen Workern, was Fehlertoleranz und Lastenausgleich bietet.
- Quittierte Verarbeitung: Konsumenten können Nachrichten quittieren und sie als verarbeitet markieren, was für eine zuverlässige Zustellung unerlässlich ist.
- Wiederholung des Verlaufs: Neue Konsumenten können den gesamten Verlauf der Ereignisse vom Anfang des Streams aus lesen.
Kernterminologie für Streams:
- Entry ID: Eine eindeutige Kennung für jede Nachricht in einem Stream, typischerweise ein Zeitstempel-Sequenz-Paar (z. B.
1678886400000-0). Sie bestimmt die Reihenfolge. - Konsument: Ein Client, der Nachrichten aus einem Stream liest.
- Konsumentengruppe: Eine logische Gruppe von Konsumenten, die zusammenarbeiten, um einen Stream zu verarbeiten. Nachrichten, die an eine Konsumentengruppe gesendet werden, werden unter ihren Mitgliedern verteilt, und nur ein Mitglied verarbeitet eine bestimmte Nachricht.
- Pending Entries List (PEL): Für Konsumentengruppen hält diese Liste Einträge, die an einen Konsumenten geliefert, aber noch nicht quittiert wurden. Unerlässlich für die Wiederherstellung nach Konsumentenausfällen.
Implementierungsbeispiel:
-
Hinzufügen von Nachrichten zu einem Stream:
redis-cli XADD mystream * sensor_id 123 temperature 25.5 # Das '*' bedeutet, dass Redis eine neue eindeutige Entry-ID generiert. # Antwort: "1678886400000-0" (Beispiel-ID)Jeder
XADD-Befehl fügt einen Eintrag mit Schlüssel-Wert-Paaren hinzu. -
Lesen aus einem Stream (mit einer Konsumentengruppe):
Erstellen Sie zuerst eine Konsumentengruppe:
redis-cli XGROUP CREATE mystream mygroup 0-0 MKSTREAM # '0-0' bedeutet, vom Anfang des Streams zu lesen. # 'MKSTREAM' erstellt den Stream, falls er noch nicht existiert.Nun kann ein Konsument in
mygrouplesen:redis-cli XREADGROUP GROUP mygroup consumer1 mystream > COUNT 1 # 'consumer1' ist der Name dieses spezifischen Konsumenten. # '>' bedeutet, neue Nachrichten zu lesen, die an diese Konsumentengruppe noch nicht gesendet wurden. # 'COUNT 1' fordert bis zu 1 Nachricht an.Beispielantwort (nach dem Hinzufügen einer Nachricht):
1) 1) "mystream" 2) 1) 1) "1678886400000-0" 2) 1) "sensor_id" 2) "123" 3) "temperature" 4) "25.5" -
Quittieren von Nachrichten: Nach der Verarbeitung quittiert der Konsument die Nachricht:
redis-cli XACK mystream mygroup 1678886400000-0 # Quittiert die Nachricht mit der angegebenen ID für 'mygroup'.
Anwendungsszenarien:
- Event Sourcing: Speichern eines vollständigen, geordneten Protokolls aller Zustandsnderungen einer Anwendung.
- Change Data Capture (CDC): Aufzeichnen von Datenbanknderungen als Ereignisstrom.
- Zuverlässige Task-Warteschlangen: Sicherstellen, dass Aufgaben genau einmal verarbeitet werden, auch bei Ausfällen von Konsumenten.
- Microservices-Kommunikation: Dauerhafter und geordneter Nachrichtenaustausch zwischen Diensten.
- IoT-Datenerfassung: Sammeln und Verarbeiten von Sensordatenströmen.
Auswahl zwischen Pub/Sub und Streams
Die Wahl zwischen Redis Pub/Sub und Streams hängt von Ihren spezifischen Anforderungen an Nachrichtenpersistenz, Zustellungsgarantien und Konsummuster ab.
| Merkmal / Aspekt | Redis Pub/Sub | Redis Streams |
|---|---|---|
| Persistenz | Keine (Fire-and-Forget) | Persistent (Nachrichten gespeichert) |
| Reihenfolge | Nicht garantiert über mehrere Publisher hinweg | Garantiert durch Entry ID |
| Zustellung | Höchstens einmal (wenn kein Subscriber, Nachricht verloren) | Mindestens einmal (mit Bestätigung und Konsumentengruppen) |
| Konsumenten-Tracking | Keine (Subscriber sind anonym) | Fortgeschritten (Konsumentengruppen verfolgen Offsets und ausstehende Nachrichten) |
| Konsumenten-Wiederherstellung | Kann verlorene Nachrichten nicht wiederherstellen | Kann ausstehende Nachrichten erneut lesen |
| Skalierbarkeit | Hoher Fan-out für Echtzeit-Broadcasts | Hoher Durchsatz für persistente Ereignisprotokolle; skaliert mit Konsumentengruppen |
| Komplexität | Einfache API | Komplexere API (Konsumentengruppen, PEL, Trimming) |
| Ideale Anwendungsfälle | Echtzeitbenachrichtigungen, transiente Ereignisse, Chat | Event Sourcing, CDC, zuverlässige Queues, IoT-Datenverarbeitung |
Für einfache, leichte Benachrichtigungen, bei denen Nachrichtenverlust akzeptabel ist und keine Persistenz erforderlich ist, ist Pub/Sub aufgrund seiner Einfachheit und hohen Leistung eine ausgezeichnete Wahl. Für Szenarien, die Dauerhaftigkeit, garantierte Zustellung, Wiederholbarkeit und komplexe Konsummuster mit mehreren Konsumenten und Fehlertoleranz erfordern, sind Redis Streams die klare Wahl. Sie bieten eine robustere und funktionsreichere Grundlage für den Aufbau anspruchsvoller ereignisgesteuerter Architekturen.
Fazit
Sowohl Redis Pub/Sub als auch Streams sind leistungsstarke Werkzeuge für die Interprozesskommunikation, bedienen jedoch unterschiedliche Zwecke. Pub/Sub eignet sich hervorragend zum Broadcasten flüchtiger Ereignisse mit minimalem Overhead, perfekt für Echtzeit-"Fire-and-Forget"-Szenarien. Streams hingegen bieten ein dauerhaftes, geordnetes und hochflexibles Ereignisprotokoll, das sie für den Aufbau robuster, ereignisgesteuerter und datenintensiver Anwendungen unverzichtbar macht. Durch das Verständnis ihrer individuellen Stärken und Schwächen können Entwickler Redis effektiv nutzen, um effiziente und skalierbare ereignisgesteuerte Systeme aufzubauen. Die Wahl des richtigen Werkzeugs für die jeweilige Aufgabe – sei es ein schneller Broadcast oder ein persistentes Ereignisprotokoll – ist entscheidend für ein robustes Systemdesign.

