Wie lässt sich das Lesen beim Event Sourcing durch CQRS optimieren
Command Query Responsibility Segregation (CQRS) und Event Sourcing werden häufig als abhängig voneinander dargestellt. Die Konzepte können aber unabhängig voneinander eingesetzt werden. Jedoch unterstützen sich die Eigenschaften von CQRS und Event Sourcing gegenseitig. Im letzten Blogbeitrag wurde das “Event Sourcing” vorgestellt. Im zweiten Teil betrachten wir, wie die Leseseite mit CQRS optimiert werden kann. Um die Vorteile und Eigenschaften von CQRS aufzeigen zu können, sollte zuerst das CAP Theorem betrachtet werden.
Das CAP-Theorem besteht aus den Punkten Consistency (Konsistenz), Availability (Verfügbarkeit) und Partition Tolerance (Partitionstoleranz). Das CAP Theorem sagt aus, dass ein verteiltes System nicht mehr als 2 dieser Punkte gleichzeitig erfüllen kann. Die Punkte können wie folgt erklärt werden:
- Consistency beschreibt die Tatsache, dass der Service die korrekte Antwort auf jede Anfrage liefern soll.
- Availability setzt voraus, dass der Service immer eine Antwort liefert. Wobei die Zeit, die für eine Antwort gebraucht wird, unberücksichtigt bleiben kann.
- PartitionTolerance stellt mehr eine Eigenschaft des unterliegenden Systems dar. Dabei muss es Ausfällen von Servern und dem Verlust von Nachrichten gegenüber tolerant sein.
Die vom CAP-Theorem definierten Punkte sind graduell zu interpretieren. Deshalb führt CQRS den Begriff Eventually Consistent (Endgültige Konsistenz) ein. Dieser beschreibt, dass die Konsistenz zwar schlussendlich immer besteht, jedoch ein kurzer Zeitraum eintreten kann, an dem ein alter Stand des Systems ausgegeben wird. Dadurch kann es für einen externen Betrachter wirken, als würde das System alle drei Punkte des CAP-Theorems erfüllen. Der Aufbau eines Beispiel Systems, das auf dem Konzept des CQRS beruht, kann in der nachfolgenden Abbildung betrachtet werden. Der Client sendet Schreib-Befehle an das Write Model, welches die Befehle in Events, wie im letzten Beitrag über Event Sourcing erläutert, umwandelt. Diese werden daraufhin im Speicher der Schreibseite persistiert, und gleichzeitig wird die Leseseite Read Model per zuverlässigem Nachrichten-Übertragungsweg über den Event informiert. Bei einer Anfrage des Clients antwortet die Leseseite mit den Daten, die sie derzeit besitzt. Dadurch kann nicht zu jedem Zeitpunkt die Konsistenz zwischen der Lese- und Schreibseite sichergestellt werden. Jedoch kann die endgültige Konsistenz garantiert werden.
Auf github haben wir das Beispiel aus dem Event Sourcing Beitrag im Branch “cqrs” um diese Funktionalität erweitert.
Die Applikation enthält ein Aktorsystem. Ein RootAktor erstellt darin einen AccountSupervisor Aktor und einen CommandBot Aktor. Der AccountSupervisor erstellt wiederum die Aktoren der einzelnen Accounts die die Konten darstellen. Der CommandBot sendet eine zufällige Anzahl von Kommandos an die Accounts. Die Kommandos werden daraufhin in Events umgewandelt und in der Event History des jeweiligen Aktors gespeichert. Der Zustand des Aktors, oder anders gesagt der Kontostand ändert sich den Events entsprechend. Die Veränderungen zur Event Sourcing Applikation sind folgende:
- Die Account Aktoren senden ihre Events an die ReadSide Aktoren.
- Der CommandBot Aktor liest nicht mehr aus den Account Aktoren, sondern nur noch über die ReadSide Aktoren.
Die ReadSide Aktoren aggregieren die Events. Zum Beispiel wird eine Summe aller MoneyDeposits zur Verfügung gestellt. Dies ist in einer reinen Event Sourcing Applikation nicht ohne Umwege möglich. Diese Applikation ist nicht für den Produktiven Betrieb gedacht, sondern nur um die Prinzipien leichter darstellen und erläutern zu können. Die ReadSide Aktoren sollten dort ihre aggregierten Daten in einem beliebigen Datenbanksystem persistieren. Ebenso sollten die Event Journale der Account Aktoren am besten in einer No-SQL Datenbank gespeichert werden.
Akka-Persistence als Erweiterung für Akka bietet die Funktionalitäten eine Event Sourcing und CQRS Applikation für den Produktiven Betrieb zu entwickeln. Es sind verschiedene Plugins für unterschiedlichste Datenbanksysteme für Akka-Persistence verfügbar. Der Google-Cloud-Datastore bietet sich als hochverfügbare, kostengünstige und hochskalierbare No-SQL Datenbank an. Ein Plugin zur Einbindung in Akka-Persistence ist auf der innFactory Github Seite verfügbar. https://github.com/innFactory/akka-persistence-gcp-datastore