it-swarm.com.de

Verwenden von Kafka als (CQRS) Eventstore. Gute Idee?

Obwohl ich schon einmal auf Kafka gestoßen bin, wurde mir erst kürzlich klar, dass Kafka vielleicht als (die Basis) eines CQRS , eventstore .

Einer der Hauptpunkte, die Kafka unterstützt:

  • Ereigniserfassung/-speicherung, alle HA natürlich.
  • Pub/Sub-Architektur
  • Möglichkeit, das Ereignisprotokoll erneut abzuspielen, sodass sich neue Abonnenten nachträglich beim System registrieren können.

Ich bin zwar nicht hundertprozentig mit CQRS/Event-Sourcing vertraut, aber dies scheint ziemlich nahe an dem zu liegen, was ein Eventstore sein sollte. Das Lustige ist: Ich finde nicht wirklich, dass Kafka als Eventstore verwendet wird, also muss mir vielleicht etwas fehlen.

Also, irgendetwas fehlt in Kafka für einen guten Eventstore? Würde es funktionieren? Produktion verwenden? Interessiert an Einsichten, Links usw.

Grundsätzlich wird der Status des Systems basierend auf den Transaktionen/Ereignissen gespeichert, die das System jemals erhalten hat, anstatt nur den aktuellen Status/Snapshot des Systems zu speichern, wie dies normalerweise der Fall ist. (Betrachten Sie es als ein Hauptbuch in der Buchhaltung: Alle Transaktionen summieren sich letztendlich zum endgültigen Zustand.) Dies ermöglicht alle Arten von coolen Dingen, aber lesen Sie einfach die bereitgestellten Links nach.

192
Geert-Jan

Kafka ist als Messaging-System gedacht, das viele Ähnlichkeiten mit einem Event-Store aufweist.

Der Kafka Cluster speichert alle veröffentlichten Nachrichten - unabhängig davon, ob sie verbraucht wurden oder nicht - für einen konfigurierbaren Zeitraum . Wenn die Aufbewahrung beispielsweise auf zwei Tage festgelegt ist, steht sie für die beiden Tage nach der Veröffentlichung einer Nachricht zum Verzehr zur Verfügung und wird anschließend verworfen, um Speicherplatz freizugeben. Die Leistung von Kafka ist in Bezug auf die so erhaltene Datengröße praktisch konstant Viele Daten sind kein Problem.

Während Nachrichten möglicherweise unbegrenzt aufbewahrt werden können, ist zu erwarten, dass sie gelöscht werden. Dies bedeutet nicht, dass Sie dies nicht als Ereignisspeicher verwenden können, aber es ist möglicherweise besser, etwas anderes zu verwenden. Schauen Sie sich EventStore für eine Alternative an.

AKTUALISIEREN

Kafka-Dokumentation :

Event-Sourcing ist eine Art des Anwendungsdesigns, bei dem Statusänderungen als zeitlich geordnete Folge von Datensätzen protokolliert werden. Kafkas Unterstützung für sehr große gespeicherte Protokolldaten macht es zu einem hervorragenden Backend für eine Anwendung, die in diesem Stil erstellt wurde.

UPDATE 2

Ein Problem bei der Verwendung von Kafka für die Ereignisbeschaffung ist die Anzahl der erforderlichen Themen. Bei der Ereignisbeschaffung gibt es in der Regel einen Datenstrom (Thema) von Ereignissen pro Entität (z. B. Benutzer, Produkt usw.). Auf diese Weise kann der aktuelle Status einer Entität wiederhergestellt werden, indem alle Ereignisse im Stream erneut angewendet werden. Jedes Kafka) -Thema besteht aus einer oder mehreren Partitionen, und jede Partition wird als Verzeichnis im gespeichert Das Dateisystem wird auch von ZooKeeper unter Druck gesetzt, da die Anzahl der ZNodes zunimmt.

104
eulerfx

Ich bin einer der ursprünglichen Autoren von Kafka. Kafka eignet sich sehr gut als Protokoll für die Ereignisbeschaffung. Es ist fehlertolerant, lässt sich auf enorme Datengrößen skalieren und verfügt über ein integriertes Partitionierungsmodell.

Wir verwenden es für mehrere Anwendungsfälle dieses Formulars bei LinkedIn. Unser Open-Source-Stream-Verarbeitungssystem Apache Samza bietet zum Beispiel integrierte Unterstützung für das Event-Sourcing.

Ich denke, Sie hören nicht viel über die Verwendung von Kafka für Event-Sourcing, vor allem, weil die Terminologie für Event-Sourcing im Consumer-Webspace, in dem Kafka ist am beliebtesten.

Ich habe ein bisschen über diesen Stil von Kafka usage here geschrieben.

261
Jay Kreps

Ich komme immer wieder auf diese Qualitätssicherung zurück. Und ich fand die vorhandenen Antworten nicht nuanciert genug, also füge ich diese hinzu.

TL; DR. Ja oder Nein, abhängig von der Verwendung Ihres Event-Sourcing.

Es gibt zwei Hauptarten von Ereignissystemen, die mir bekannt sind.

Downstream-Ereignisprozessoren = Ja

In einem solchen System passieren Ereignisse in der realen Welt und werden als Fakten aufgezeichnet. Wie ein Lagersystem, um Paletten von Produkten zu verfolgen. Es gibt grundsätzlich keine widersprüchlichen Ereignisse. Alles ist schon passiert, auch wenn es falsch war. (Das heißt, die Palette 123456 wurde auf LKW A abgestellt, war jedoch für LKW B vorgesehen.) Später werden die Fakten über Berichtsmechanismen auf Ausnahmen überprüft. Kafka scheint für diese Art von nachgelagerter Ereignisverarbeitungsanwendung gut geeignet zu sein.

In diesem Zusammenhang ist es verständlich, warum Kafka Leute es als Event-Sourcing-Lösung befürworten. Weil es ziemlich ähnlich ist, wie es bereits in Click-Streams verwendet wird. Personen, die den Begriff Event Sourcing (im Gegensatz zu Stream Processing) verwenden, beziehen sich wahrscheinlich auf die zweite Verwendung ...

Anwendungsgesteuerte Wahrheitsquelle = Nr

Diese Art von Anwendung deklariert ihre eigenen Ereignisse als Ergebnis von Benutzeranforderungen, die die Geschäftslogik durchlaufen. Kafka funktioniert in diesem Fall aus zwei Hauptgründen nicht gut.

Fehlende Entitätsisolation

In diesem Szenario muss der Ereignisstrom für eine bestimmte Entität geladen werden können. Der häufigste Grund hierfür ist die Erstellung eines vorübergehenden Schreibmodells für die Geschäftslogik, mit der die Anforderung verarbeitet werden soll. Dies zu tun ist in Kafka unpraktisch. Die Verwendung von Topic-per-Entity könnte dies ermöglichen, mit der Ausnahme, dass dies kein Starter ist, wenn es möglicherweise Tausende oder Millionen von Entities gibt. Dies liegt an technischen Grenzen in Kafka/Zookeeper.

Einer der Hauptgründe für die Verwendung eines vorübergehenden Schreibmodells auf diese Weise besteht darin, Änderungen an der Geschäftslogik kostengünstig und einfach bereitzustellen.

Die Verwendung von topic-per-type wird stattdessen für Kafka empfohlen, dies würde jedoch das Laden von Ereignissen für jede Entität dieses Typs erfordern, nur um Ereignisse für eine einzelne Entität abzurufen. Da Sie anhand der Protokollposition nicht erkennen können, welche Ereignisse zu welcher Entität gehören. Selbst wenn Sie Snapshots verwenden, um von einer bekannten Protokollposition aus zu starten, kann dies eine erhebliche Anzahl von Ereignissen sein, die durchlaufen werden müssen.

Fehlende Konflikterkennung

Zweitens können Benutzer aufgrund gleichzeitiger Anforderungen gegen dieselbe Entität Rennbedingungen erstellen. Es ist möglicherweise nicht wünschenswert, widersprüchliche Ereignisse zu speichern und sie nachträglich zu beheben. Daher ist es wichtig, widersprüchliche Ereignisse verhindern zu können. Um die Anforderungslast zu skalieren, werden in der Regel zustandslose Dienste verwendet, während Schreibkonflikte durch bedingte Schreibvorgänge verhindert werden (nur schreiben, wenn das letzte Entitätsereignis #x war). A.k.a. Optimistische Parallelität. Kafka unterstützt keine optimistische Parallelität. Selbst wenn es auf Themenebene unterstützt würde, müsste es bis auf Entitätsebene reichen, um effektiv zu sein. Um Kafka zu verwenden und Konflikte zu vermeiden, müssten Sie einen statusbehafteten, serialisierten Writer auf Anwendungsebene verwenden. Dies ist eine wesentliche architektonische Anforderung/Einschränkung.

Weitere Informationen


Aktualisierung per Kommentar

Der Kommentar wurde gelöscht, aber die Frage lautete: Was wird dann für die Speicherung von Ereignissen verwendet?

Es scheint, dass die meisten Leute ihre eigene Ereignisspeicherimplementierung auf einer vorhandenen Datenbank rollen. In nicht verteilten Szenarien wie internen Back-Ends oder eigenständigen Produkten wird gut dokumentiert ein SQL-basierter Ereignisspeicher erstellt. Und es gibt Bibliotheken, die zusätzlich zu Datenbanken verschiedener Art verfügbar sind. Es gibt auch EventStore , das für diesen Zweck erstellt wurde.

In verteilten Szenarien habe ich verschiedene Implementierungen gesehen. Das Panther-Projekt von Jet verwendet Azure CosmosDB mit der Funktion "Feed ändern", um Listener zu benachrichtigen. Eine weitere ähnliche Implementierung, von der ich in AWS gehört habe, ist die Verwendung von DynamoDB mit der Streams-Funktion, um Listener zu benachrichtigen. Der Partitionsschlüssel sollte wahrscheinlich die Stream-ID für die beste Datenverteilung sein (um das Ausmaß der Überbereitstellung zu verringern). Eine vollständige Wiedergabe über Streams in Dynamo ist jedoch teuer (lesen und kostenmäßig). Daher wurde dieses Impl auch für Dynamo Streams eingerichtet, um Ereignisse in S3 zu speichern. Wenn ein neuer Hörer online geht oder ein vorhandener Hörer eine vollständige Wiedergabe wünscht, würde er S3 lesen, um zuerst aufzuholen.

Mein aktuelles Projekt ist ein Szenario mit mehreren Mandanten, und ich habe mein eigenes Szenario auf Postgres gerollt. Etwas wie Citus scheint für die Skalierbarkeit geeignet zu sein, die Partitionierung nach tentant + stream.

Kafka ist in verteilten Szenarien immer noch sehr nützlich. Es ist ein nicht triviales Problem, die Ereignisse jedes Dienstes anderen Diensten auszusetzen. Ein Event Store ist normalerweise nicht dafür gebaut, aber genau das macht Kafka gut. Jeder Dienst verfügt über eine eigene interne Wahrheitsquelle (kann eine Ereignisspeicherung oder eine andere sein), hört jedoch auf Kafka, um zu wissen, was "außerhalb" geschieht. Der Dienst kann auch Ereignisse an Kafka senden, um die Außenwelt über interessante Aktivitäten des Dienstes zu informieren.

36
Kasey Speakman

Sie können Kafka als Ereignisspeicher verwenden, dies wird jedoch nicht empfohlen, auch wenn dies nach einer guten Wahl aussieht:

  • Kafka garantiert nur mindestens eine Zustellung und es gibt Duplikate im Event Store, die nicht entfernt werden können. Update: Hier kannst du nachlesen, warum es mit Kafka so schwierig ist und was es Neues gibt, um dieses Verhalten endlich zu erreichen: - https://www.confluent.io/blog/exactly-once-semantics-are-possible-heres-how-Apache-kafka-does-it/
  • Aufgrund der Unveränderlichkeit gibt es keine Möglichkeit, den Ereignisspeicher zu manipulieren, wenn sich die Anwendung entwickelt und Ereignisse transformiert werden müssen (es gibt natürlich Methoden wie Upcasting, aber ...). Einmal könnte man sagen, dass Sie Ereignisse niemals transformieren müssen, aber das ist nicht die richtige Annahme, es könnte eine Situation geben, in der Sie eine Sicherungskopie des Originals erstellen, diese jedoch auf die neuesten Versionen aktualisieren. Dies ist eine gültige Anforderung in ereignisgesteuerten Architekturen.
  • Kein Ort, an dem Schnappschüsse von Entitäten/Aggregaten und die Wiedergabe gespeichert bleiben, wird langsamer und langsamer. Das Erstellen von Snapshots ist aus langfristiger Sicht ein Muss für den Ereignisspeicher.
  • Da Kafka Partitionen verteilt sind, sind sie im Vergleich zu Datenbanken schwer zu verwalten und zu sichern. Datenbanken sind einfach einfacher :-)

Also, bevor Sie Ihre Wahl treffen, überlegen Sie zweimal. Der Ereignisspeicher als Kombination von Schnittstellen auf Anwendungsebene (Überwachung und Verwaltung), SQL/NoSQL-Speicher und Kafka als Broker ist die bessere Wahl, als Kafka beide Rollen zu übernehmen, um eine vollständige Lösung für alle Funktionen zu erstellen.

Der Event Store ist ein komplexer Service, der mehr erfordert, als Kafka bieten kann, wenn Sie es ernst meinen mit der Anwendung von Event-Sourcing, CQRS, Sagas und anderen Mustern in einer ereignisgesteuerten Architektur und der Beibehaltung einer hohen Leistung.

Fühlen Sie sich frei, meine Antwort in Frage zu stellen! Sie mögen vielleicht nicht, was ich über Ihren Lieblingsmakler mit vielen überlappenden Fähigkeiten sage, aber dennoch, Kafka war nicht als Ereignisspeicher konzipiert, sondern eher als leistungsstarker Broker und Puffer, um beispielsweise schnelle Produzenten und langsame Konsumentenszenarien abzuwickeln.

Weitere Informationen zu den möglichen Problemen finden Sie im Open-Source-Framework von eventuate.io microservices: http://eventuate.io/

Update vom 8. Februar 2018

Ich beziehe keine neuen Informationen aus Kommentaren ein, stimme aber einigen dieser Aspekte zu. In diesem Update werden einige Empfehlungen für ereignisgesteuerte Microservice-Plattformen erläutert. Wenn Sie es ernst meinen mit dem robusten Design und der höchstmöglichen Leistung im Allgemeinen, werde ich Ihnen einige Hinweise geben, die Sie interessieren könnten.

  1. Verwenden Sie Spring nicht - es ist großartig (ich benutze es selbst oft), aber es ist schwer und gleichzeitig langsam. Und es ist überhaupt keine Microservice-Plattform. Es ist "nur" ein Framework, das Ihnen bei der Implementierung hilft (viel Arbeit dahinter ...). Andere Frameworks sind "nur" REST oder JPA oder anders fokussierte Frameworks. Ich empfehle die wahrscheinlich klassenbeste Open-Source-Plattform für vollständige Mikroservices, die auf die reinen Wurzeln von Java zurückgreift: https://github.com/networknt

Wenn Sie sich über die Leistung wundern, können Sie sich mit der vorhandenen Benchmark-Suite vergleichen. https://github.com/networknt/microservices-framework-benchmark

  1. Benutze Kafka überhaupt nicht :-)) Es ist ein halber Scherz. Ich meine, während Kafka großartig ist, ist es ein weiteres maklerzentriertes System. Ich denke, die Zukunft liegt in maklerlosen Nachrichtensystemen. Sie werden überrascht sein, aber es gibt schnellere Systeme als Kafka :-), natürlich müssen Sie auf eine niedrigere Ebene gelangen. Schauen Sie sich Chronik an.

  2. Für den Ereignisspeicher empfehle ich die überlegene Postgresql-Erweiterung TimescaleDB, die sich auf die Hochleistungsdatenverarbeitung von Zeitreihen (Ereignisse sind Zeitreihen) in großem Umfang konzentriert. Natürlich sind CQRS, Event Sourcing (Replay, etc.) in light4j Framework integriert, das Postgres als Low Storage nutzt.

  3. Schauen Sie sich für Nachrichten die Chronicle Queue, Map, Engine, Network an. Ich meine, diese altmodischen maklerzentrierten Lösungen loszuwerden und auf das Micro Messaging System (eingebettetes) zu setzen. Chronicle Queue ist sogar noch schneller als Kafka. Aber ich bin damit einverstanden, dass es nicht alles in einer Lösung ist und Sie etwas Entwicklung tun müssen, sonst gehen Sie und kaufen Sie die Enterprise-Version (bezahlt eine). Am Ende wird der Aufwand, aus Chronicle eine eigene Messaging-Ebene zu erstellen, durch die Beseitigung der Belastung durch die Wartung des Kafka-Clusters bezahlt.

14
kensai

Ja, Sie können Kafka als Ereignisspeicher verwenden. Dies funktioniert sehr gut, insbesondere mit der Einführung von Kafka Streams , das eine kafka-native Methode zur Verarbeitung Ihrer Daten bietet Ereignisse in akkumuliert Zustand, den Sie abfragen können .

Bezüglich:

Möglichkeit, das Ereignisprotokoll erneut abzuspielen, sodass sich neue Abonnenten nachträglich beim System registrieren können.

Das kann schwierig sein. Ich habe das hier ausführlich behandelt: https://stackoverflow.com/a/48482974/74197

7

Ja, Kafka funktioniert gut im Event-Sourcing-Modell speziell für CQRS. Sie müssen jedoch beim Festlegen der TTLs für Themen darauf achten, dass kafka nicht entwickelt wurde Für dieses Modell können wir es jedoch sehr gut verwenden.

0
Brijendra Verma