2017-10-01 2 views
2

Ich versuche, ein Event-Sourcing-System mit Postgres zu implementieren. Der beste Weg zu erklären ist ein Beispiel. Nehmen wir an, dass meine Ereignisse irgendwann eine Person beschreiben müssen. Und ich habe die folgenden Ereignisse:Event Sourcing mit inkonsistentem Verhalten von Ereignissen

  1. PersonCreatedEvent (Wert = 100, Bereich = "id", date = ..)
  2. AgeUpdated (Wert = 10, Bereich = "Alter", date = ..)
  3. LastNameUpdate (value = "newLastName", Feld = "Nachname", date = ..)
  4. LocationUpdated (Wert = (lat, long), Feld = "location", date = ..)
  5. BalanceUpdated (Wert = 1000, Feld = "Balance", Datum = ..)

Ereignis 1 wird nur einmal im Leben einer Person vorkommen.
Ereignisse 2 - 3 Kann mehrmals vorkommen.
Ereignisse 4 - 5 Kann viele Male passieren.

Am Ende des Tages, werde ich mit einem Tisch am Ende, die mit Ereignissen 4 und 5

so konsequent vor allem, wenn ich 10 Millionen Menschen in meinem Tisch habe, könnte ich Milliarden von Ereignissen während 99% von ihnen sind im Grunde 4 und 5. Dies wird zu einem riesigen Datenspeicher, nicht sicher, dass Postgres damit schön spielen wird. (Es kann .. aber mit erheblichen Arbeit \ Infrastruktur erhöhen.)

Dies ist nur ein Beispiel, meine Entität könnte aus 100 Feldern kombiniert werden, was mindestens 100 Ereignisse pro Einheit bedeutet. Einige der Felder haben die Merkmale der Ereignisse 4 und 5.

Der Mehrwert der Verwendung von Event Sourcing in meinem Fall ist, dass ich eine Geschichte inhärent auf meine Entität, die eine Produktanforderung in meinem Fall ist.

Was ist die beste Vorgehensweise in diesem Fall? Vielleicht häufiger Eigenschaften sollten anderswo behandelt werden?

UPDATE: Ein anderes Beispiel ist ein Geräteaggregat.

  1. DeviceManufacturerUpdated (value = "cisco", Feld = "Hersteller", date = ..)
  2. DeviceNameUpdated (value = "foo", Feld = "name", date = ...)
  3. DeviceIpUpdated (value = "1.1.1.1", Feld = "ip", date = ...)
  4. DeviceLocationUpdated (value = "neuen Standort", Feld = "location", date = ...)
  5. DeviceLastSeenUpdated (Wert = "irgendein Datum", field = "last_seen", Datum = ...)

Hier gilt das gleiche 1. Ereignis 1 kann 5 mehrmals täglich mehrmals Heppen 3. Ereignis 3 Heppen kann 4. Ereignis 4 kann Heppen täglich Heppen einmal 2. Ereignis 2 können.Ereignis 5 kann jede Minute

Heppen wenn ich das über Postgress bin der Umsetzung ich mit einem riesigen Tisch wird am Ende meist enthält Ereignisse 4 und 5.

+0

Snapshot könnte helfen, aber ich nehme an, in einem bestimmten Punkt muss ich etwas mit der Größe meiner Datenbank tun. (Die Größe ist ein Ergebnis des "Typs" der Ereignisse, die ich fortsetze). Also wird irgendwann ein Snapshot übrig bleiben, aber ich werde die History-Funktionen verlieren (nach dem Löschen von Ereignissen). Es fühlt sich an, als würde ich etwas falsch machen, wenn mein Tisch zu 99% aus demselben Ereignistyp besteht. es fühlt sich an, als ob es einen Raum für eine Optimierung gibt, die mir nicht bekannt ist ..: - | Was denken Sie? – Tomer

Antwort

2

mein Unternehmen könnte von 100 Feldern kombiniert werden, was bedeutet, bei mindestens 100 Veranstaltungen pro Einheit

das wahrscheinlich zeigt an, dass Ihre Veranstaltungen Ihre Einheiten am falschen Korn modellieren. Ein "Ding", das in der Domäne passiert, die 100% der Eigenschaften betrifft, sollte normalerweise in Ihrem Verlauf als ein Ereignis mit vielen Daten und nicht als viele Ereignisse mit jeweils einem Datum erscheinen.

Das bedeutet nicht, dass Sie nicht mit einer potenziell großen Anzahl von Ereignissen enden werden, besonders wenn Sie viele Entitäten haben.

Es gibt zwei allgemeine Antworten auf diese Frage. Man leiht sich aus ; Wir denken über den Bereich in Form von Aggregaten nach - Staatssammlungen, die voneinander isoliert werden können. Da die Entitäten isoliert werden können, spielt es keine Rolle, ob sie sich im selben dauerhaften Speicher befinden oder ob der Store geschichtet ist. So können Sie die Ereignisse verteilen.

Eine andere Möglichkeit - in vielen Bereichen gibt es einen natürlichen zeitlichen Rhythmus; Am Ende des Geschäftsjahres rollen Sie den aktuellen Status auf, verwenden diesen Status, um den Beginn eines neuen Streams zu markieren, und setzen den alten zurück.

Es gibt auch die Möglichkeit der Speicherbereinigung - mit den richtigen Datenstrukturen können Hintergrundprozesse die Historie durcharbeiten und Ereignisse mit geringem Wert ersetzen.

Die Hauptsache ist, von der Idee der Crud Sourcing wegzukommen.

Im weiteren Sinne müssen Sie auch darüber nachdenken, ob das Geschäft einen Wert aus der Verfolgung der gesamten Geschichte einer Entität ableitet oder nicht. Sie sollten keine Ereignishistorien für Entitäten verwenden, bei denen die Kosten/Nutzen-Analyse Ihnen vorschreibt, Informationen in Dokument-Snapshots zu speichern.

3

Für mich scheint es, dass Sie ein (granulares) CRUD-System haben und Sie brauchen nicht Event sourcing. Das ist nicht schlecht, Sie müssen den Zustand nicht nur rekonstruieren, indem Sie alle Ereignisse aus dem Verlauf erneut anwenden, um die Befehle zu validieren. In Ihrem Fall vielleicht der aktuelle Zustand ist genug.

Wenn Sie die Idee von Ereignissen (mehr wie wenn Sie benötigen) dann könnten Sie eine Event log verwenden. Dies ist wie Ereignis-Sourcing, aber Sie verwenden Ereignisse in einer konsistenten Art und Weise und nur für die Read-Seite.

Um Entitäten nach Verhalten zu teilen, können Sie in jedem Fall DDD verwenden. Vielleicht könnten Sie zwei Aggregate mit derselben ID haben: PersonDetails und PersonAccountBalance? Warum? Weil Sie nie den Namen (oder den Standort) der Person benötigen, wenn Sie überprüfen, ob sein Guthaben positiv sein sollte, wenn Sie sein Guthaben aktualisieren (ungefähr, dass Sie update his balance und nicht makeADeposit oder withdrawMoney sind, aber es hängt von Ihrer Domäne ab).

+0

Danke! Ich denke, das BalanceUpdated war ein wenig Missleading ... es war ein schlechtes Beispiel. Event-Sourcing machte Sinn, wenn ich Geschichte für eine Person bekommen wollte und sie zu jedem Zeitpunkt beschreiben wollte. Lassen Sie uns aggregierte Person ansprechen. Wenn es eine Eigenschaft hat, die sehr häufig aktualisiert wird, sollte es differentiell adressiert werden? Ich meine, es fühlt sich an, als wäre etwas falsch, wenn mein Tisch zu 99% aus dem gleichen Ereignistyp besteht, – Tomer

+0

@Tomer Es kommt wirklich auf jeden Fall an. Ich muss die genauen Geschäftsdetails kennen, um es sicher zu sagen ... –

+0

Sie haben völlig Recht. Ich habe ein Beispiel hinzugefügt, das meinen Anwendungsfall besser darstellt. Sag mir was du denkst. – Tomer

2

Für mich sieht es seltsam aus, ein AgeUpdated- und BalanceUpdated-Ereignis im selben Aggregatstamm zu haben. Ereignisse, die Etwas in ihrem Namen aktualisiert hat, flüstert mir, dass es entweder ein CRUD-Anwendungsfall ist oder dass Sie mehr an Ihrem Aggregatdesign arbeiten müssen.

Gibt es eine andere Gruppierung von Transaktionen, die statt der Person interessant sein kann? Um das herauszufinden, sollten Sie sich überlegen, welche Invarianten halten sollten. Das heißt, in welchen Situationen kann die Transaktion fehlschlagen und was sollte immer wahr sein? (Lesen Sie dazu domain-driven-design Aggregate, wenn Sie nicht haben)

Wenn Sie eine Art Transaktion für Konto zum Beispiel machen, ist vielleicht die Geschäftsregel, dass das Konto nicht mehr als $ 100 überzeichnet werden kann. In diesem Fall können Sie das Konto als das aggregierte Stammverzeichnis anstelle der Person verwenden, die das Konto besitzt.

Um das volle Gleichgewicht für eine Person zu erhalten, benötigen Sie ein Lesemodell, das alles für einen Benutzer aggregiert.

Aber alles hängt von Ihrem Anwendungsfall ab.

Viel Glück!

+0

Danke! Ich denke, der BalanceUpdated war ein wenig Missleading. weil es in der Tat nicht zu der Person Aggregat gehört. Lassen Sie uns für eine Sekunde annehmen, dass das Ereignis mit dem Aggregat Person zusammenhängt (vielleicht ist locationupdated besser?), Wie soll ich einen Fall behandeln, in dem dieses Ereignis tatsächlich am richtigen Ort ist, aber seine Häufigkeit ist * 100 größer als die anderen Ereignisse? – Tomer

+0

Es hängt davon ab, was Ihr Anliegen ist. Ich denke, es ist nicht von Natur aus falsch, viele ähnliche Ereignisse für eine aggregierte Wurzel zu haben. Wenn Sie sich Gedanken über die Leistung machen, stellen Sie sicher, dass Sie feststellen, dass es sich wirklich um ein Problem handelt, bevor Sie etwas Komplexeres wie Snapshots implementieren. Wenn Sie mit Ihrer Domänenlogik experimentieren möchten, ohne zu viel Infrastruktur aufzubauen, wäre es cool, wenn Sie unseren neuen Service https://serialized.io zum Erstellen von CQRS/ES-Anwendungen ausprobieren möchten (ich bin einer der Mitbegründer) . –

Verwandte Themen