Kafkaを(CQRS)イベントストアとして使用する。良いアイデア?


219

以前にカフカに出会ったことはありますが、最近、カフカがCQRSイベントストア(のベース)として使用されている可能性があることに最近気付きました

Kafkaがサポートする主なポイントの1つ:

  • イベントのキャプチャ/保存、もちろんすべてのHA。
  • パブ/サブアーキテクチャ
  • 新しいサブスクライバーが事後にシステムに登録できるようにするイベントログを再生する機能。

確かに私はCQRS /イベントソーシングに100%精通しているわけではありませんが、これはイベントストアのあるべき姿にかなり近いようです。面白いことに、イベントストアとして使用されているKafkaについてはそれほど多くの情報を見つけることができません。

それで、それが良いイベントストアになるためにカフカから欠けているものは何ですか?それはうまくいくでしょうか?それを使って生産?洞察、リンクなどに興味がある

基本的にシステムの状態は、通常行われているシステムの現在の状態/スナップショットを保存するだけでなく、システムが受信したトランザクション/イベントに基づいて保存されます。(会計の総勘定元帳と考えてください:すべてのトランザクションは最終的に最終状態になります)これにより、あらゆる種類のすばらしいことが可能になりますが、提供されているリンクを読むだけです。


こんにちはGeert-Jan。振り返ってみると、この問題にどのように対処しましたか?関連する質問があります(ここで公開:stackoverflow.com/questions/58763727/…)。Kafkaの採用を提案するほとんどの人は、追加ログの不変性、高スループット、パーティション順序の保証のポイントに依存しているようです。トピック内の高速検索に関連する問題(エンティティ「再構築」の場合)、トランザクションの原子性、パーティション間の順序付けがないことがわかります。 (100%の順序保証は、1つのパーティションのみを使用することを意味します
tony _008

私はそのサイドプロジェクトを終えたので、結局それを説得しませんでした。はっきりとした答えはありません。恐れています
Geert-Jan

回答:


119

Kafkaは、イベントストアと多くの類似点があるメッセージングシステムであることを意図していますが、イントロを引用します。

Kafkaクラスターは、構成れた期間、パブリッシュされたすべてのメッセージを(それらが消費されたかどうかに関係なく)保持します。たとえば、保持が2日間に設定されている場合、メッセージがパブリッシュされてから2日間は、メッセージを使用できます。その後、メッセージは破棄され、スペースが解放されます。Kafkaのパフォーマンスはデータサイズに関して事実上一定であるため、大量のデータを保持することは問題ではありません。

したがって、メッセージは無期限に保持される可能性がありますが、削除されることが期待されます。これは、これをイベントストアとして使用できないという意味ではありませんが、他の何かを使用する方がよい場合があります。別の方法については、EventStoreご覧ください。

更新

Kafkaのドキュメント

イベントソースは、状態変化が時系列のレコードシーケンスとしてログに記録されるアプリケーション設計のスタイルです。保存された非常に大きなログデータに対するKafkaのサポートは、このスタイルで構築されたアプリケーションの優れたバックエンドになります。

アップデート2

イベントソーシングにKafkaを使用する際の1つの懸念は、必要なトピックの数です。通常、イベントソーシングでは、エンティティ(ユーザー、製品など)ごとにイベントのストリーム(トピック)があります。このように、ストリームのすべてのイベントを再適用することで、エンティティの現在の状態を再構成できます。Kafkaの各トピックは1つ以上のパーティションで構成され、各パーティションはファイルシステム上のディレクトリとして保存されます。znodeの数が増えると、ZooKeeperからの圧力もかかります。


16
私はカフカを見ていて、別の懸念がありました。楽観的同時実行性については何も気づきませんでした。理想的には、「オブジェクトの最新のイベントがまだNである場合にのみ、このイベントをアイテムN + 1として追加します。」
ダリアン

2
@Darien:おそらく、RedisがKafkaに(Redis Notificationsを使用して)フィードする設定を使用しています。Redisは楽観的な同時実行を可能にするため(Watch / multi-execを使用)、これは機能するはずです
Geert-Jan

2
@Darien私はイベントソーシングの専門家ではありませんが、一般的に言えば、イベントはすでに歴史的に発生したことの記録であるため、楽観的な同時実行性は必要ないと私は理解しています。
ジョン

4
@John競合していないイベントの信頼できる順序付けがすでにある場合、それらがどこにあるかが実際のイベントストアテクノロジーであることを意味し、Kafkaはそれらを配布するためのセカンダリシステムとして使用されているだけだと思います。
ダリアン

1
ここにも貴重な情報があります:groups.google.com/forum
#!

283

私はカフカの原作者の一人です。Kafkaは、イベントソーシングのログとして非常によく機能します。フォールトトレラントであり、巨大なデータサイズに対応し、パーティションモデルが組み込まれています。

LinkedInでこのフォームのいくつかの使用例に使用します。たとえば、オープンソースストリーム処理システムであるApache Samzaには、イベントソーシングのサポート組み込まれています。

イベントソーシングの用語が、カフカが最も人気のあるコンシューマーWebスペースではあまり普及していないように思われるため、イベントソーシングにKafkaを使用することについてはあまり聞いていないと思います。

私はカフカの使用状況のこのスタイルについて少し書かれているここ


2
そのリンクを投稿するつもりでした:)素晴らしいブログ投稿。質問が多いのでコメントして頂けたら良かったです。@ Geert-Janは "Lambdaアーキテクチャ"も確認しています。これは非常によく似ており、その名前はStormの作者から付けられています。主に、多くの例である種のhadoopベースのイベントログを使用しています
Sebastien Lorber

6
@ジェイ:私はこのトピックに再び関心を示したので、公開されたメッセージが一定期間後に期限切れになるようにカフカが設計されているように見えるという事実について少し詳しく説明してもらえますか?Kafkaをイベントソースとして使用する場合、メッセージは無期限に保存する必要があります。それはおそらく設定可能ですが、これは問題を引き起こしますか?
Geert-Jan

2
カフカとイベントストアの比較はありますか?具体的には、ProjectionsというイベントストアでFRPに焦点を当てることが好きです。カフカ/サムザにそのようなものはありますか?
CMCDragonkai 2014年

4
@ Geert-JanのJayへの質問にも興味があります。Kafkaは、ドメイン集約(数百万と考える)ごとにイベント(トピック)のストリームが必要になるため、トランザクション側の実際のイベントソーシングには適していません。ただし、GetEventStoreなどからイベントを供給するのに最適です。しかし、これは無限に保持されるイベント(私たちの場合)でのみ機能し、いくつかの簡単なコメントを除いて、これはKafkaのサポートされるユースケースではないようです。私はここで間違っていますか?たとえば、Samzaは、時間ベースの保持またはキーベースの保持の2つのシナリオのみがあると想定しています。他の人があります...
スティーブン・ドリュー

3
@eulerfxイベントソースシステムのストレージとしてKafkaを使用する場合、どのように楽観的ロック/同時実行を実装する必要がありますか?
Krzysztof Branicki 2017

51

私はこのQAに戻ってきます。そして、私は既存の答えに十分なニュアンスがあるとは思わなかったので、これを追加します。

TL; DR。イベントソーシングの使用状況に応じて、はいまたはいいえ。

私が認識しているイベントソースシステムには2つの主要な種類があります。

ダウンストリームイベントプロセッサ=はい

この種のシステムでは、イベントは現実の世界で発生し、事実として記録されます。製品のパレットを追跡する倉庫システムなど。基本的に競合するイベントはありません。たとえそれが間違っていたとしても、すべてはすでに起こっています。(つまり、パレット123456がトラックAに積まれましたが、トラックBに予定されていました。)その後、レポートメカニズムを介して、例外について例外がチェックされます。Kafkaは、この種の下流のイベント処理アプリケーションに適しているようです。

この文脈では、カフカの人々がイベントソーシングソリューションとしてそれを支持している理由は理解できます。クリックストリームなどですでに使用されている方法とよく似ているためです。ただし、(ストリーム処理ではなく)イベントソーシングという用語を使用している人は、2番目の使用法を参照している可能性があります...

アプリケーション制御の信頼できる情報源=いいえ

この種のアプリケーションは、ユーザーリクエストがビジネスロジックを通過した結果として、独自のイベントを宣言します。この場合、2つの主な理由でKafkaはうまく機能しません。

エンティティの分離の欠如

このシナリオでは、特定のエンティティのイベントストリームを読み込む機能が必要です。これの一般的な理由は、リクエストの処理に使用するビジネスロジックの一時的な書き込みモデルを構築することです。これを行うことはカフカでは非現実的です。エンティティごとのトピックを使用すると、これが可能になる可能性があります。ただし、エンティティが数千または数百万ある場合のスターターではありません。これは、Kafka / Zookeeperの技術的な制限によるものです。

このように一時書き込みモデルを使用する主な理由の1つは、ビジネスロジックの変更を安価で簡単に展開できるようにすることです。

Kafkaでは、代わりにトピックごとのタイプを使用することをお勧めしますが、単一のエンティティのイベントを取得するためだけに、そのタイプのすべてのエンティティのイベントをロードする必要があります。ログの位置では、どのイベントがどのエンティティに属しているかはわかりません。スナップショットを使用して既知のログ位置から開始する場合でも、大量のイベントが発生する可能性があります。

競合検出の欠如

第2に、ユーザーは同じエンティティに対する同時要求が原因で競合状態が発生する可能性があります。競合するイベントを保存し、事後にそれらを解決することは非常に望ましくない場合があります。したがって、競合するイベントを防止できることが重要です。リクエストの負荷をスケーリングするには、条件付き書き込みを使用して書き込みの競合を防止しながらステートレスサービスを使用するのが一般的です(最後のエンティティイベントが#xの場合にのみ書き込み)。別名楽観的同時実行。Kafkaはオプティミスティック並行性をサポートしていません。たとえそれがトピックレベルでそれをサポートしたとしても、それは効果的であるためにエンティティレベルまでずっと下にある必要があるでしょう。Kafkaを使用してイベントの競合を防ぐには、アプリケーションレベルでステートフルなシリアル化されたライターを使用する必要があります。これは重要なアーキテクチャ要件/制限です。

さらに詳しい情報


コメントごとに更新

コメントは削除されましたが、質問は次のようなものでした。その場合、人々は何をイベントストレージに使用するのでしょうか。

ほとんどの人は、既存のデータベースの上に独自のイベントストレージ実装を実装しているようです。内部のバックエンドやスタンドアロン製品などの非分散シナリオの場合、SQLベースのイベントストアを作成する方法が詳しく文書化されています。そして、さまざまな種類のデータベースの上に利用可能なライブラリがあります。この目的のために構築されたEventStoreもあります。

分散シナリオでは、いくつかの異なる実装を見てきました。JetのPantherプロジェクトは、Azure CosmosDBを使用し、変更フィード機能を使用してリスナーに通知します。AWSで聞いたもう1つの類似の実装は、DynamoDBとそのStreams機能を使用してリスナーに通知することです。パーティションキーは、(過剰なプロビジョニングの量を減らすために)最良のデータ分散のためのストリームIDである必要があります。ただし、Dynamoのストリーム全体での完全な再生にはコストがかかります(読み取りおよびコストの面で)。したがって、この実装は、Dynamo StreamsがS3にイベントをダンプするためにも設定されました。新しいリスナーがオンラインになるとき、または既存のリスナーが完全な再生を必要とするとき、最初に追いつくためにS3を読み取ります。

私の現在のプロジェクトはマルチテナントのシナリオであり、私はPostgresの上に自分のプロジェクトを展開しました。Citusのようなものはスケーラビリティに適しているようで、テナント+ストリームごとに分割されます。

Kafkaは、分散シナリオでも依然として非常に役立ちます。各サービスのイベントを他のサービスに公開することは重要な問題です。イベントストアは通常そのために構築されていませんが、それがまさにカフカがうまくやっていることです。各サービスには独自の内部情報源(イベントストレージなど)がありますが、「外部」で何が起こっているかを知るためにKafkaをリッスンします。サービスはまた、イベントをKafkaに投稿して、サービスが行った興味深いことを「外部」に通知する場合もあります。


1
@Dominik更新セクション(2番目の段落)でEventStoreについて言及しました。戻ってリンクします。私はそれを試しました、そしてそれは印象的なパフォーマンスを持っています。私たちの小さなチームにとって、当面は別のデータベースを導入しないことがより重要であると考えられたため、Postgres(ビューにも使用されます)。今後、または将来の製品でEventStoreに移行する可能性があります。
Kasey Speakman

2
@KaseySpeakmanトピックはパーティションと同じではありません。トピックには1つ以上のパーティションがあります。パーティションでは、常に、グループごとに1つのコンシューマーのみが存在することが保証されています。それを利用するような方法でエンティティを分割します。エンティティごとのトピックや、エンティティごとのパーティションは必要ありません。同じエンティティにアドレス指定されたすべてのコマンドが同じパーティションに移動することを保証するような方法でそれらを分割する必要があるだけです。
Andrew Larsson

1
@KaseySpeakman多くのエンティティが単一のパーティションを共有できます。イベントを再生して、常にエンティティの状態をイベントストアから直接読み込む必要があると誰が言ったのですか。行ごとのGreg Youngの実装に厳密に従わずに同じ概念を実現する他の方法があります。
Andrew Larsson

1
@AndrewLarssonエンティティごとにパーティション分割しない場合、エンティティレベルで競合するイベントをどのように防止しますか?同時実行の競合に完全に戻ってきたので、おそらく、プロダクションでのイベントソーシング(ストリーム処理ではない)にKafkaをどのように使用したかについて、独自の記事を媒体に投稿する必要があります。タイプ別のパーティションを使用し、エンティティレベルの同時実行制御を使用せずにそれを実行する方法。私はそれを読んだり、同意しなかったとしてもコメントであなたを荒らしたりはしません。
Kasey Speakman、

2
@KaseySpeakmanこの方法でKafkaを使用することは決して簡単ではありません。しかし、CQRSとイベントソーシングを真剣に検討した規模であれば、簡単な方法で物事を行う余裕はありません。同時実行モデルはスケールに直接影響します。任意に選択しないでください。また、HTTPは信頼性の高いトランスポートではありません。また、その規模の場合、失われたメッセージや重複したメッセージの問題の解決に時間を費やす余裕はありません。これはすべて、クライアントとコマンドプロセッサの間でKafkaを使用することで解決できますが、はい、複雑さを犠牲にします。
Andrew Larsson

20

イベントストアとしてKafkaを使用することもできますが、良い選択のように見えるかもしれませんが、使用はお勧めしません。

  • Kafkaは、少なくとも1回の配信のみを保証し、イベントストアに削除できない重複があることを保証します。 更新: ここでは、Kafkaがなぜそれほど難しいのか、そしてこの動作を最終的に実現する方法に関する最新のニュースを読むことができます。https//www.confluent.io/blog/exactly-once-semantics-are-possible-heres-how -apache-kafka-does-it /
  • 不変性のため、アプリケーションが進化してイベントを変換する必要がある場合にイベントストアを操作する方法はありません(もちろん、アップキャストのようなメソッドがありますが...)。イベントを変換する必要はないと言ったことがあるかもしれませんが、これは正しい仮定ではありません。元のバックアップを実行するが、最新バージョンにアップグレードする状況が発生する可能性があります。これは、イベント駆動型アーキテクチャーで有効な要件です。
  • エンティティ/アグリゲートのスナップショットを永続化し、再生する場所がどんどん遅くなります。スナップショットの作成は、長期的な観点からのイベントストアの機能である必要があります。
  • 与えられたKafkaパーティションは分散され、データベースと比較して管理およびバックアップが困難です。データベースは単純です:-)

そのため、選択する前に、よく考えます。アプリケーションレイヤーインターフェイス(監視と管理)の組み合わせとしてのイベントストア、SQL / NoSQLストア、ブローカーとしてのKafkaは、Kafkaが両方の役割を処理して完全な機能の完全なソリューションを作成するよりも優れた選択肢です。

イベントストアは複雑なサービスであり、イベントソーシング、CQRS、Sagas、その他のパタ​​ーンをイベントドリブンアーキテクチャに適用することを真剣に考え、高いパフォーマンスを維持する場合にKafkaが提供できるもの以上のものを必要とします。

私の答えに気軽に挑戦してください!重複する機能がたくさんあるお気に入りのブローカーについて私が言うのは気に入らないかもしれませんが、それでもカフカはイベントストアとしてではなく、高速なプロデューサーと低速なコンシューマーのシナリオを同時に処理するための高性能ブローカーとバッファーとして設計されました。例えば。

潜在的な問題の詳細については、eventuate.ioマイクロサービスのオープンソースフレームワークをご覧ください。http//eventuate.io/

2018年2月8日の更新

私はコメントからの新しい情報を取り入れませんが、それらの側面のいくつかに同意します。この更新は、マイクロサービスのイベント駆動型プラットフォームに関するいくつかの推奨事項に関するものです。マイクロサービスの堅牢な設計と一般的に考えられる最高のパフォーマンスについて真剣に考えている場合は、興味のあるヒントをいくつか提供します。

  1. Springは使用しないでください。すばらしい(自分でよく使用します)が、重くて遅い。そして、それはまったくマイクロサービスプラットフォームではありません。それは1つを実装するのに役立つ「単なる」フレームワークです(これの背後にある多くの作業..)他のフレームワークは、「単なる」軽量のRESTまたはJPA、あるいは別の方法でフォーカスされたフレームワークです。おそらくクラス最高のオープンソースの完全なマイクロサービスプラットフォームを利用することをお勧めします。これは純粋なJavaルートに戻ってきます。https//github.com/networknt

パフォーマンスについて疑問がある場合は、既存のベンチマークスイートと比較できます。 https://github.com/networknt/microservices-framework-benchmark

  1. Kafkaはまったく使用しないでください:-))冗談です。つまり、カフカは素晴らしいですが、ブローカー中心の別のシステムです。将来はブローカーレスのメッセージングシステムにあると思います。驚くかもしれませんが、カフカシステムよりも高速です:-)もちろん、より低いレベルに下げる必要があります。クロニクルを見てください。

  2. イベントストアには、TimescaleDBと呼ばれる優れたPostgresql拡張機能をお勧めします。これは、大量の高パフォーマンス時系列データ処理(イベントは時系列です)に焦点を当てています。もちろん、CQRS、イベントソーシング(再生などの機能)は、低ストレージとしてP​​ostgresを使用するlight4jフレームワークに組み込まれています。

  3. メッセージングについては、Chronicle Queue、Map、Engine、Networkをご覧ください。つまり、この昔ながらのブローカー中心のソリューションを取り除き、マイクロメッセージングシステム(組み込みシステム)を採用するということです。Chronicle Queueは実際にはKafkaよりもさらに高速です。しかし、すべてが1つのソリューションであるわけではなく、開発を行う必要があることに同意します。それ以外の場合は、Enterpriseバージョン(有料のもの)を購入します。最後に、クロニクルから構築するための努力は、Kafkaクラスターを維持する負担を取り除くことによって、独自のメッセージングレイヤーに支払われます。


興味深い見方。いくつかの点について詳しく説明しますか?> Kafkaは少なくとも1回は配信を保証し、イベントストアには削除できない重複があります。ちょうど一回だけ配達するようなものがあるとほのめかしているようです。afaik(そして私はそれについてかなり確信しています)分散システムにはそのようなものはありません。2)あなたのポイント2に関して:(イベントソーシング/ dddd)の古典派は、イベントは本質的に不変であると考えています。すなわち、彼らは起こった、過去を変える方法はない。実際の用途は何ですか?振り返ってそれらを変更する場合?ありがとう!
Geert-Jan

1.)各メッセージが1回だけ処理されるようにするHazelcast。2.)サービスコードで_V2のようなものが好きではないので、バックアップして古いイベントを新しいバージョンにアーカイブして再作成するか(元の真実はそのままです)、またはこの機能をイベントに直接非表示/構築できます。スナップショット機能を保存するので、アップキャストの単一ポイント->イベントストアがあります。これに対するあなたの解決策は何ですか?
ケンサイ2017年

1)消費者の少なくとも1回+べき等性。つまり、イベントがすでに表示されているかどうかを確認します。その場合はスキップしてください。さらに良いことに、べき等のアクションがあります。もちろん、これは常に可能であるとは限りません。2)イベントのバージョン管理が必要になることはありません。私は常にイベント自体を真実の情報源として扱い、これまでに必要となるすべての情報を含めています。これを行うことで、異なるイベント構造やイベントに関するデータが必要になる状況に遭遇したことはありません。しかしおそらくymmv。実際にイベントを更新する必要がある状況を聞くことに興味があります。
Geert-Jan、

1.)を選択することができます。2.)その後、データ構造は最初から完璧でした:-)ラッキー、ハハ。現在のプロジェクトでは必要ないかもしれませんが、eventuate.ioのフォークにプラットフォーム全体を構築しています。軽いeventuate 4jから取られたいくつかの高性能JEEのみのアプローチとマージします...この全体の議論は、stackoverflowに関するコメントの場ではありませんあなたはダイビングに興味がある場合は、より深い私はこの記事をお勧めします。leanpub.com/esversioning/read
kensai

1
ちなみに、Kafkaは現在、1回のみの配信をサポートしています。箇条書き1を更新
OneCricketeer

8

はい、Kafkaをイベントストアとして使用できます。これは、特にKafkaストリームの導入で非常にうまく機能します。これは、イベントを処理してクエリできる累積状態にするためのKafkaネイティブの方法を提供します

について:

新しいサブスクライバーが事後にシステムに登録できるようにするイベントログを再生する機能。

これは注意が必要です。ここで詳しく説明しました:https : //stackoverflow.com/a/48482974/741970


0

はい、Kafkaはイベントソーシングモデル、特にCQRSでうまく機能しますが、トピックのTTLを設定する際には注意が必要です。また、Kafkaはこのモデル用に設計されていないことを常に覚えておいてください。


0

私は軸索フレームワークとカフカのサポートを一緒に見るべきだと思います

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.