Playbook
CQRS (Command Query Responsibility Segregation) in Produktion: Konsistenz, Fehler und Wiederherstellung (CQRS In Produktion Konsistenz Fehler Und Wiederherstellung)
Wie bleibt CQRS in Produktion sicher? Consistency Lag, Duplicate Events, Reordering, Projection Recovery, Retries, DLQs und Saga-Strategien.
Wie diese Fehler für Nutzer aussehen
Wenn ein Bankguthaben zwei Sekunden verzögert ist, kann ein Nutzer denken, dass Geld verschwunden ist. Wenn ein Like-Zähler zwei Sekunden verzögert ist, akzeptieren es die meisten Nutzer vielleicht. Derselbe technische Lag erzeugt zwei unterschiedliche Produktrisiken.
Kommt dieselbe OrderPlaced Nachricht zweimal an, kann Inventory zweimal reduziert werden. Production-Konzepte sollten daher nicht nur als Definitionen, sondern über ihre Wirkung auf Nutzer und Geschäft gelesen werden.
Die eigentliche Frage in Produktion
Der Happy Path ist einfach: Ein Command wird akzeptiert, ein Event veröffentlicht und eine Projektion aktualisiert. In Produktion kommt eine Nachricht zweimal, ein Consumer fällt zurück, eine Projektion bricht oder ein Nutzer findet die gerade erstellte Bestellung nicht.
Command accepted → event published → projection delayed → user refreshes
"Ist meine Bestellung verschwunden?"
Partial Failure ist in verteilten Systemen keine Ausnahme. Dieses Kapitel entfernt Fehler nicht; es zeigt, wie Datenkorrektheit, Nutzervertrauen und Recovery Time beim Fehler erhalten bleiben.
Begriffe bei der ersten Verwendung
📦 Consistency Lag
Die Zeit zwischen erfolgreichem Write und aktualisiertem Read Model.
📦 Retry
Ein kontrolliertes Wiederholen nach einem vorübergehenden technischen Fehler.
📦 Dead-Letter Queue (DLQ)
Eine Queue für Nachrichten, die der normale Flow nicht verarbeiten kann.
📦 Checkpoint
Die letzte Event-Position, die eine Projektion sicher verarbeitet hat.
Eventual Consistency bedeutet nicht, dass Daten falsch sind. Unterschiedliche Modelle erreichen dieselbe Tatsache zu unterschiedlichen Zeiten. Ist das akzeptabel, muss das Produkt es klar erklären; ist es das nicht, braucht eine kritische Query eine andere Konsistenzstrategie.
Jede Verteidigung hat einen Grund
- Ein Checkpoint wird gespeichert, weil ein Replay wissen muss, wo eine Projektion sicher fortsetzen kann.
- Idempotenz ist nötig, weil ein Duplicate Event bei zweiter Anwendung reale Geschäftswirkung wie Inventory oder Payment beschädigt.
- Retry wird begrenzt, weil eine fehlerhafte Nachricht durch Wiederholung nicht repariert wird, sondern Last und falsche Wirkung verstärken kann.
- Eine DLQ wird genutzt, weil eine im normalen Flow ungelöste Nachricht sichtbaren Owner und Untersuchung braucht.
- Der Partition Key ist die Aggregate ID, weil die kausale Reihenfolge eines Aggregates wichtiger ist als globale Event-Reihenfolge.
- Wir machen Replay, weil verifizierte Event-Historie auch bei defekter Projektion die korrekte Quelle bleibt.
Consistency Lag ist eine Produktentscheidung
Wenn eine bezahlte Bestellung zwei Sekunden nicht in einer Liste erscheint, fühlt es sich wie Datenverlust an. Definieren Sie zuerst den sichtbaren Vertrag: Wie schnell muss jeder Screen nach einer Aktion aktuell sein?
POST /orders → 202 Accepted + orderId + version
GET /orders/{id}?minVersion=42
→ aktuelle Sicht, wenn Projektion 42 erreicht
→ Status "in Verarbeitung", solange sie es nicht hat
Optimistic UI, Polling oder Wait-for-Version können helfen. Sie entfernen Lag nicht, weil die eigentliche Aufgabe darin liegt, seine Bedeutung dem Nutzer ehrlich zu erklären. Das Ergebnis der Command Side bleibt die Quelle der Wahrheit für kritische Entscheidungen.
Duplicate Events und Reordering
At-least-once-Zustellung macht Duplicates normal. Ein Order Event zweimal zu verarbeiten kann Inventory zweimal reduzieren. Ein Consumer muss Event-ID und Aggregate-Version prüfen.
if event.id already processed: ignore
if event.version <= projection.version: ignore
apply event
store checkpoint and event id
Das ist ein O(1)-Lookup im Mittel oder ein O(log n)-B-Tree-Lookup. Wenn Reihenfolge nur in einer Partition garantiert ist, verwenden Sie Aggregate ID als Partition Key, weil die kausale Reihenfolge einer Bestellung wichtiger ist als globale Reihenfolge.
Retry, DLQ und der Entscheidungspunkt des Operators
Nicht jeder Fehler sollte wiederholt werden. Ein Network Timeout kann vorübergehend sein; ein ungültiges Event Schema ist dauerhaft.
| Fehlertyp | Reaktion | Warum |
|---|---|---|
| Timeout / 503 | Retry mit Exponential Backoff | Eine Abhängigkeit kann sich erholen |
| Rate Limit | Verzögerter Retry | Erholung ohne Last zu verstärken |
| Schema Validation | DLQ + Alarm | Retry repariert die Nachricht nicht |
| Business Rule Failure | Persistieren, prüfen, kompensieren | Automatischer Retry kann falsche Wirkung verstärken |
Eine DLQ ist kein Papierkorb. Jede Nachricht braucht Owner, Review-Fenster, Replay-Prozedur und Alarm.
Wie eine defekte Projektion wiederhergestellt wird
Eine Projektion ist kein Cache, sondern eine neu aufbaubare Geschäftssicht.
1. Consumer stoppen oder neue Projektionsversion erstellen
2. Letzten sicheren Checkpoint validieren
3. Event Stream kontrolliert erneut abspielen
4. Counts und Sample-Daten validieren
5. Traffic auf neue Projektion lenken
6. Lag und Error Rate beobachten
Replay-Kosten sind linear O(n) in der Event-Anzahl. Snapshots oder segmentiertes Replay können sie senken, aber ein Snapshot ist nicht Source of Truth. Weil Recovery auf verifizierter Event-Historie beruhen muss.
Der Fehlerpfad einer Saga
Wenn Payment im E-Commerce fehlschlägt, darf Inventory nicht dauerhaft reserviert bleiben. Eine Saga ist kein technischer Rollback; sie ist fachliche Kompensation.
Reserve inventory → Capture payment → Create shipment
payment fails → Release inventory
Auch Kompensation muss idempotent sein: ReleaseInventory zweimal auszuführen darf Inventory nicht zweimal erhöhen. Choreography bleibt für lokale Flows leicht; Orchestration gibt einem langen Workflow State Machine und einen Beobachtungspunkt.
Observability
Messen Sie Consumer Lag, Retry Count, DLQ Depth, Checkpoint Age, Duplicate Rate und End-to-End Action Time. Tragen Sie eine Trace ID vom Command über Event und Consumer bis zur Query.
Zuordnungen, die falsche Sicherheit schaffen
❌ Retry = Zuverlässigkeit
✓ Retry ist nur bei transienten Fehlern und idempotenter Arbeit sicher.
❌ DLQ = Recovery
✓ Eine DLQ startet einen Untersuchungs- und Replay-Prozess.
❌ Replay = immer sicher
✓ Ohne Versionierung und isolierte Side Effects kann Replay Wirkung wiederholen.
❌ Eventual Consistency = zufällige Verzögerung
✓ Lag muss gemessen, mit dem Produkt akzeptiert und Nutzern erklärt werden.
Production-Readiness-Check
- Gibt es ein Ziel für den nutzersichtbaren Consistency Lag?
- Ist jeder Consumer bei Duplicates und Out-of-Order Events sicher?
- Trennt Retry transiente und permanente Fehler?
- Hat jede DLQ-Nachricht Owner und Replay Runbook?
- Können Sie eine Projektion mit Produktionsdaten sicher neu aufbauen?
- Sind Saga-Kompensationen idempotent?
Wenn Sie jede Frage nicht mit Evidenz beantworten können, wirkt das System vielleicht skalierbar, ist aber noch nicht betreibbar.
Was sollte im Gedächtnis bleiben?
- Eventual Consistency ist ein über User Experience gesteuerter Vertrag.
- Duplicates und Reordering sind normale verteilte Zustellung, keine Edge Cases.
- Retry, DLQ und Replay sind ein Recovery-System.
- Eine nicht neu aufbaubare Projektion wird zu Operational Debt.
- Eine Saga rollt nicht zurück; sie kompensiert Geschäftswirkung.
Production Architecture zeigt sich nicht, wenn Nachrichten beim ersten Versuch richtig ankommen, sondern wenn sie doppelt, verspätet oder in unerwarteter Reihenfolge eintreffen.
FAQ
Häufige Fragen
Was ist Consistency Lag?
Die Zeit zwischen erfolgreichem Write und aktualisiertem Read Model.
Was ist Retry?
Ein kontrolliertes Wiederholen nach einem vorübergehenden technischen Fehler.
Stimmt es, dass „Retry = Zuverlässigkeit“?
Retry ist nur bei transienten Fehlern und idempotenter Arbeit sicher.
Was legt dieser Teil fest?
Partial Failure ist in verteilten Systemen keine Ausnahme. Dieses Kapitel entfernt Fehler nicht; es zeigt, wie Datenkorrektheit, Nutzervertrauen und Recovery Time beim Fehler erhalten bleiben. Eventual Consistency ist ein über User Experience gesteuerter Vertrag. Der Happy Path ist einfach: Ein Command wird akzeptiert, ein Event veröffentlicht und eine Projektion aktualisiert. In Produktion kommt eine Nachricht zweimal, ein Consumer fällt zurück, eine Projektion bricht oder ein Nutzer findet die gerade erstellte Bestellung nicht.
Gelernte Engineering-Prinzipien
- Consistency Lag muss ein vom Produkt akzeptierter und für Nutzer sichtbarer Vertrag sein.
- Idempotente Consumer sind für Duplicates, Reordering und Replay zwingend.
- Recovery ist eine vorab entworfene Fähigkeit mit Checkpoints, Runbooks und Observability.
Weiterlesen
Weiterlesen
Verwandte Beitrage
CQRS (Command Query Responsibility Segregation) in verteilten Systemen: Events, Broker und Projektionen
Wie funktioniert CQRS in verteilten Systemen? Ein praxisnaher Leitfaden zu Domain Events, Message Brokern, Projektionen, Outbox, Idempotenz und Eventual…
Verwandte Beitrage
Wie funktioniert eine CQRS (Command Query Responsibility Segregation)-Pipeline? Anatomie von Command- und Query-Flows
Was ist eine CQRS Request Pipeline? Wie durchläuft eine HTTP-Anfrage Controller, MediatR, Pipeline Behaviors, Handler, Outbox und Read Model?
Verwandte Beitrage
DDD in Produktion: Verteilte Systeme und Modernisierungsstrategien
Wie bleibt DDD unter Production-Change tragfähig? Ein Leitfaden zu Event Storming, Saga, Transactional Outbox, Anti-Corruption Layer und…