GH GambleHub

Event Sourcing: Grundlagen

Was ist Event Sourcing

Event Sourcing (ES) ist eine Möglichkeit, den Status von Domänenobjekten nicht als „aktuelle Zeile“ zu speichern, sondern als unveränderliches Ereignisprotokoll, das alles beschreibt, was passiert ist. Der aktuelle Zustand des Aggregats wird durch die Faltung (Wiederholung) seiner Ereignisse erhalten, und alle Darstellungen zum Lesen werden als Projektionen auf diesem Protokoll erstellt.

Die wichtigsten Konsequenzen:
  • Die Geschichte sei die „primäre Quelle der Wahrheit“, der Zustand die Projektion der Geschichte.
  • Jeder Zustand kann neu reproduziert, überprüft und erklärt werden (Audit).
  • Das Hinzufügen neuer Ansichten und Analysen erfordert keine Migrationen alter „Snapshots“ - es genügt, Ereignisse zu verlieren.

Grundlegende Begriffe

Ein Aggregat ist eine Domäneneinheit der Konsistenz mit klaren Invarianten (Order, Payment, UserBalance).
Ein Ereignis ist eine unveränderliche Tatsache, die in der Vergangenheit aufgetreten ist ('payment. authorized`, `order. shipped`).
Der Event Store ist ein App-Onli-Protokoll, das die Reihenfolge der Ereignisse innerhalb der Einheit sicherstellt.
Aggregatversion - Nummer des zuletzt angewendeten Ereignisses (für optimistische Konzentration).
Snapshot ist ein periodischer Abdruck des Zustands, um die Faltung zu beschleunigen.
Projektion (Lesemodell) ist eine materialisierte Ansicht zum Lesen/Suchen/Berichten (oft asynchron).

Funktionsweise (Fluss von Befehlen → Ereignissen → Projektionen)

1. Der Client sendet einen Befehl ('CapturePayment', 'PlaceOrder').
2. Das Aggregat validiert Invarianten und erzeugt, wenn alles in Ordnung ist, Ereignisse.
3. Ereignisse werden dem Event Store mit einer Versionsprüfung (optimistic concurrency) atomar hinzugefügt.
4. Projektionsprozessoren folgen dem Ereignisablauf und aktualisieren die Lesemodelle.
5. Wenn die Einheit für den nächsten Befehl geladen wird, wird der Zustand wiederhergestellt: der Snapshot (falls vorhanden) → die Ereignisse nach dem Snapshot.

Gestaltung von Veranstaltungen

Erforderliche Attribute (Kernel)

json
{
"event_id": "uuid",
"event_type": "payment. authorized. v1",
"aggregate_type": "Payment",
"aggregate_id": "pay_123",
"aggregate_version": 5,
"occurred_at": "2025-10-31T10:42:03Z",
"payload": { "amount": 1000, "currency": "EUR", "method": "card" },
"meta": { "trace_id": "t-abc", "actor": "user_42" }
}
Empfehlungen:
  • Benennung: 'Domäne. action. v{major}`.
  • Additivität: Neue Felder sind optional, ohne die Bedeutung der alten zu ändern.
  • Minimalismus: nur Fakten, keine Duplizierung leicht wiederherstellbarer Daten.

Verträge und Schemata

Schemen fixieren (Avro/JSON Schema/Protobuf) und Kompatibilität auf CI prüfen.
Für „brechende“ Änderungen gibt es eine neue Dur-Version der Veranstaltung und eine parallele Veröffentlichung von 'v1 '/' v2' für den Zeitraum der Migration.

Wettbewerbsfähiger Zugang: optimistic concurrency

Regel: Die Aufzeichnung neuer Ereignisse ist nur möglich, wenn 'expected _ version = = current_version'.

Pseudocode:
pseudo load: snapshot(state, version), then apply events > version new_events = aggregate. handle(command)
append_to_store(aggregate_id, expected_version=current_version, events=new_events)
//if someone has already written an event between load and append, the operation is rejected -> retray with reload

So garantieren wir die Integrität von Invarianten ohne verteilte Transaktionen.

Schnappschüsse (Faltbeschleunigung)

Machen Sie einen Snap-Shot alle N Ereignisse oder einen Timer.
Храните `snapshot_state`, `aggregate_id`, `version`, `created_at`.
Überprüfen und verfolgen Sie immer die Ereignisse nach dem Schnappschuss (vertrauen Sie nicht nur dem Abdruck).
Entfernen Sie Snap-Shots, damit sie aus dem Protokoll neu erstellt werden können (speichern Sie keine „magischen“ Felder).

Projektionen und CQRS

ES wird natürlich mit CQRS kombiniert:
  • Schreibmodell = Aggregate + Event Store.
  • Read-Modelle = Projektionen, die durch Ereignisse aktualisiert werden (Redis-Karten, OpenSearch für die Suche, ClickHouse/OLAP für Berichte).
  • Projektionen sind idempotent: Die wiederholte Verarbeitung des gleichen 'event _ id' ändert das Ergebnis nicht.

Schaltungsentwicklung und Kompatibilität

Additive-first: Fügen Sie Felder hinzu; Ändern Sie nicht die Typen/Semantik.
Für komplexe Änderungen: Veröffentlichen Sie neue Arten von Ereignissen und schreiben Sie Projektionsmigratoren.
Halten Sie die doppelte Aufzeichnung ('v1' + 'v2') für eine Übergangszeit aufrecht und schießen Sie' v1', wenn alle Projektionen fertig sind.

Sicherheit, PII und das „Recht auf Vergessen“

Die Geschichte enthält oft sensible Daten. Ansätze:
  • Minimieren Sie PII in Ereignissen (IDs statt Daten, Teile in geschützten Seiten).
  • Krypto-Löschung: Verschlüsseln Sie die Felder und zerstören Sie den Schlüssel, wenn Sie die Löschung anfordern (das Ereignis bleibt bestehen, aber die Daten sind nicht verfügbar).
  • Ereignis-Revisionen: 'user. piiredacted. v1 'mit dem Ersatz empfindlicher Felder in Projektionen (die Geschichte behält die Tatsache der Bearbeitung bei).
  • Retentionsrichtlinien: Für einige Domains kann ein Teil der Ereignisse im WORM-Speicher archiviert werden.

Leistung und Skalierung

Partitionierung: Die Reihenfolge ist wichtig innerhalb der Einheit - partitionieren Sie nach 'aggregate _ id'.
Kaltstart: Schnappschüsse + periodische „Verdichtung“ der Faltung.
Batch-Append: Gruppieren Sie Ereignisse mit einer einzigen Transaktion.
Backpressure und DLQ für Projektionsprozessoren; Messen Sie den Lag (Zeit und Anzahl der Nachrichten).
Event Store-Indexierung: Schneller Zugriff nach'(aggregate_type, aggregate_id) 'und Zeit.

Testen

Spezifizierungstests für Aggregate: Szenario „Befehle → erwartete Ereignisse“.
Projektionstests: Geben Sie den Ereignisfluss ein und überprüfen Sie den materialisierten Status/die Indizes.
Wiederholbarkeitstests: Stellen Sie die Projektionen „von Grund auf“ auf dem Stand neu zusammen - stellen Sie sicher, dass das Ergebnis übereinstimmt.
Chaos/Latenz: Verzögerungen und Takes einspritzen, Idempotenz prüfen.

Beispiele für Domänen

1) Zahlungen

Ereignisse: 'Zahlung. initiated`, `payment. authorized`, `payment. captured`, `payment. refunded`.
Invarianten: Sie können nicht 'capture' ohne' authorized'; die Beträge sind nicht negativ; Die Währung ist unverändert.
Projektionen: „Zahlungskarte“ (KV), Transaktionssuche (OpenSearch), Reporting (OLAP).

2) Bestellungen (E-Commerce)

Veranstaltungen: 'bestellen. placed`, `order. paid`, `order. packed`, `order. shipped`, `order. delivered`.
Invarianten: Statusübergänge im Zustandsdiagramm; Stornierung möglich bis „versandt“.
Projektionen: Liste der Benutzeraufträge, SLA-Dashboards nach Status.

3) Bilanzen (Finanzen/iGaming)

Veranstaltungen: 'balance. deposited`, `balance. debited`, `balance. credited`, `balance. adjusted`.
Harte Invariante: Balance geht nicht weg <0; Befehle sind idempotent in 'operation _ id'.
Kritische Operationen werden direkt aus dem Aggregat abgelesen (strikte Konsistenz), UI aus der Projektion (eventual).

Typische Event Store-Struktur (DB-Variante)

events

`event_id (PK)`, `aggregate_type`, `aggregate_id`, `version`, `occurred_at`, `event_type`, `payload`, `meta`

Index: „(aggregate_type, aggregate_id, Version)“.

snapshots

`aggregate_type`, `aggregate_id`, `version`, `state`, `created_at`

Index: „(aggregate_type, aggregate_id)“.

consumers_offsets

'consumer _ id', 'event _ id '/' position', 'updated _ at' (für Projektionen und Retlay).

Häufig gestellte Fragen

Muss ES überall eingesetzt werden?
Nein. ES ist nützlich, wenn Auditing, komplexe Invarianten, Reproduzierbarkeit und unterschiedliche Datenrepräsentationen wichtig sind. Für eine einfache CRUD ist dies redundant.

Was ist mit „state of the art“ -Anfragen?
Entweder lesen Sie aus der Projektion (schnell, eventual) oder - aus der Einheit (teurer, aber streng). Kritische Operationen verwenden normalerweise den zweiten Weg.

Brauche ich einen Kafka/Stream-Broker?
Event Store - die Quelle der Wahrheit; Der Broker eignet sich für die Verteilung von Ereignissen an Projektoren und externe Systeme.

Was tun mit dem „Recht auf Vergessen“?
Minimieren Sie PII, verschlüsseln Sie empfindliche Felder und wenden Sie Krypto-Löschung/Revision in Projektionen an.

Wie migriere ich alte Daten?
Schreiben Sie ein Skript für die retrospektive Ereignisgenerierung („Re-Highstory“) oder beginnen Sie mit „state-as-is“ und veröffentlichen Sie Ereignisse nur für neue Änderungen.

Anti-Pattern

Event Sourcing „aus Gewohnheit“: Kompliziert das System ohne Domain-Vorteil.
Fat Events: aufgeblähte Payload's mit PII und Takes - Brems- und Compliance-Probleme.
Fehlende optimistische Concurrency: Verlust von Invarianten bei Rennen.
Nicht reproduzierbare Projektionen: keine Replikation/Snap-Shots → manuelle Fixierungen.
Rohe CDCs als Domänenereignisse: OBD-Schaltungslecks und starre Konnektivität.
Vermischung von Innen- und Integrationsveranstaltungen: Nach außen ein stabilisiertes „Schaufenster“ veröffentlichen.

🚨 Check-in> Checkliste für die Produktion
  • Aggregate, Invarianten und Ereignisse (Titel, Versionen, Schemata) sind definiert.
  • Der Event Store sorgt für Ordnung innerhalb des Aggregats und eine optimistische Concurrency.
  • Snap-Shots und ein Plan, sie neu zu erstellen, sind enthalten.
  • Projektionen sind idempotent, es gibt DLQs und Lags-Metriken.
  • Schemata werden auf CI validiert, Versionsrichtlinien dokumentiert.
  • PII wird minimiert, Felder werden verschlüsselt, es gibt eine Strategie des „Vergessens“.
  • Nachbildungen der Projektionen auf dem Prüfstand geprüft; Es gibt einen Notfallplan.
  • Dashboards: Appendegeschwindigkeit, Projektionsfehler, Anwendungsfehler, Retrayanteil.

Summe

Event Sourcing macht die Geschichte des Systems zu einem erstklassigen Artefakt: Wir erfassen Fakten, daraus reproduzieren wir den Zustand und bauen jegliche Darstellungen frei auf. Dies führt zu Audits, Veränderungsresistenz und Analyseflexibilität - vorausgesetzt, Sie sind in Bezug auf Schemata, Wettbewerbskontrolle und den kompetenten Umgang mit sensiblen Daten diszipliniert.

Contact

Kontakt aufnehmen

Kontaktieren Sie uns bei Fragen oder Support.Wir helfen Ihnen jederzeit gerne!

Integration starten

Email ist erforderlich. Telegram oder WhatsApp – optional.

Ihr Name optional
Email optional
Betreff optional
Nachricht optional
Telegram optional
@
Wenn Sie Telegram angeben – antworten wir zusätzlich dort.
WhatsApp optional
Format: +Ländercode und Nummer (z. B. +49XXXXXXXXX).

Mit dem Klicken des Buttons stimmen Sie der Datenverarbeitung zu.