2016-11-20 15 views
4

Jonathan Oliverからの不適切な投稿を読んだことがあります。CQRSの読み取り側での順序違反イベントの処理

http://blog.jonathanoliver.com/cqrs-out-of-sequence-messages-and-read-models/

我々が使用するソリューションは、メッセージをデキューするために、前の配列と、すべてのメッセージが 受信されるまで、「保持テーブル」に配置することです。以前のすべてのメッセージが受信されたら、 メッセージを保持テーブルから取り出し、 適切なハンドラを通して順番に実行します。 すべてのハンドラが正常に実行されると、保持テーブルからメッセージが削除され、読み取ったモデルの更新が にコミットされます。

ドメインがイベントを公開し、 に適切なシーケンス番号を付けるため、これは私たちのために機能します。これがなければ、以下の解決方法 は不可能ではないにしても、はるかに難しくなります。

このソリューションでは、永続ストレージ メカニズムとしてリレーショナルデータベースを使用していますが、 ストレージエンジンの関係性の側面は使用していません。同時に、このすべてに警告があります。 メッセージ2,3,4が届いても、メッセージ1は届かない場合は、 は適用されません。エラーメッセージ メッセージ1を処理している場合、またはメッセージ1が何らかの形で消失した場合にのみ、シナリオが発生します。幸いにも、 メッセージハンドラのエラーを修正するのは簡単で、 はメッセージを再実行します。または、メッセージが失われた場合は、 をイベントストアから直接読み込んで再構築してください。

イベントの不足をイベントストアにいつでも頼むことができるとのことについて、いくつか質問がありました。

  1. CQRSの書き込み側は、イベントの再生を要求する側のサービスを公開する必要がありますか。たとえば、イベント1に は受信されていませんが、2,3,4,3が受信できた場合は、イベントストアを サービスでリクエストして1から開始してイベントを再公開することができますか?
  2. このサービスはCQRSの書き込み側の責任ですか?
  3. これを使用して読み込みモデルを再構築するにはどうすればよいですか?
+0

RabbitMqで「再試行」アプローチを使用していて、うまくいきました。何回か再試行してもそれでもうまくいかない場合は、このイベントをデッドレターキューに入れてシーケンス番号をリセットして、それ以上のイベントを正しく処理できるようにしてください。通常、アプリケーションの順序外イベントの原因は何ですか? – IlliakaillI

+0

私は複数のイベントを生成するいくつかの特定のコマンドを持っています。私はまだ何も実装していませんが、可能性のある出来事の出来事はさまざまです。私のイベントパブリッシャーも非同期で動作します。したがって、いくつかのイベントが順番に公開されない可能性もあります。私は私のイベントのシーケンス番号に頼っています。 私はリトライを試みます。あなたがそれについて少し詳しく説明できるなら、私はそれを答えとしてマークすることができます。 –

+0

私は私の答えのコメントのセクションでより詳しい説明を追加しました。 – IlliakaillI

答えて

1

シーケンス番号がある場合は、現在のイベントが異常である状況を検出できます。 currentEventNumber!= lastReceivedEventNumber + 1

これを検出すると、例外がスローされます。あなたのサブスクライバが「再試行」の仕組みを持っている場合、このイベントをもう1秒程度で再度処理しようとします。この時間の間に、以前の出来事が処理され、シーケンスが正しいことがかなり良いチャンスです。これは、アウトオブオーダーのイベントがめったに起きない場合の解決策です。

このような状況に直面している場合は、グローバルロックメカニズムを実装する必要があります。これにより、特定のイベントを順番に処理できるようになります。 たとえば、MSSQLでsp_getapplockを使用して、特定の状況でグローバルな「クリティカルセクション」の動作を実現していました。 Apache ZooKeeperは、分散アプリケーションの複数の部分が単なる単純なロック以上のものを必要とする場合、さらに複雑なシナリオに対処するためのフレームワークを提供します。

+0

私は特定のマルチプレイヤーゲームがこのような状況をどのように処理しているかを見ていました。ゲームは約100ms持続するキャッシュを内蔵しています。直前のイベントがない場合、イベントを適用する前に100ms待機します。潜在的なスケーラビリティの問題のために、私は少しロックを使用することを躊躇しています。 Btw実装で不足しているイベントをイベントストアにどのように頼んでいますか? –

+0

このシステムを堅牢にするには、集約側のすべての種類のキャッシュに非常に注意する必要があります。あなたのアプリケーションが突然失敗するとどうなりますか?私の経験から、キャッシュされたイベントのアプローチは、スケールされません。私たちのビジネスケースでは、分散型の24/7フォールトトレラントサーバーを構築していました。つまり、別々の物理マシンに少なくとも2つのアグリゲータープロセスのインスタンスを用意する必要があります。分割シナリオを避けたい場合は、3つの別々のインスタンスを並行して実行することを検討する必要があります。 – IlliakaillI

+0

>>実装で不足しているイベントをイベントストアに問い合わせるにはどうすればよいですか? さて、私たちはrabbitmqを使用していて、後に空白のサービスバスに切り替えました。どちらのサービスも納品保証のための機能を提供します。基本的には、アグリゲーター側のトランザクションの終了時にイベントが正常に処理されたことをキューサービスに通知します。 – IlliakaillI

0

あなたがここで説明しているのは、イベントソース(ES)です。コマンドモデルで発行されたイベントを永続ストレージに格納します。 イベントタイプ、コマンドモデルID(集約ルートID)、コマンドモデルタイプ(集約ルートタイプ)別にストアドイベントを再生します。 ESを持つことの利点があります。後でこれらのイベントを再生して、新しいタイプのクエリモデルを作成することもできます。 ESアプローチを使用すると、UnitOfWorkスコープのアプリケーショントランザクションを使用することもできます。コミット時に、発行されたイベントは永続化され、イベントリスナーに配信されます(QMメンテナンスサービス)。コミットステージでの検証には、シーケンス番号(db)による並行アクセスのチェックが含まれている必要があります。

+0

残念ながら、これは投稿された質問のいずれにも答えません。私は前にESを使ってCQRSを実装しましたが、この質問は、順序が狂っている/欠けているイベントのコンテキストに固有のものです。 –

+0

配送が遅れると、状況が変わりやすくなります。シーケンスメッセージを超過したことが検出された場合は、遅れて配送を延期します。しかし、配達そのものは合意されなければならない。あなたが選んだメッセージ配信スタイルは何ですか?たぶん一回、少なくとも一回、または一回だけ。メッセージ配信は、インフラストラクチャ(RabbitMQ、Kafka)によって処理されますか? Eq、Kafkaは、各グループへの順序どおりのトピック配信を保証します。定義された時間だけメッセージを永続させることもできるため、消費者は数時間オフラインになり、メッセージが配信されます。 – hellxcz

+0

私はRabbitMQを使用しており、「少なくとも1回」の配送を保証しています。そのため、メッセージの冪等をイベントハンドラにも実装する必要があります。 –

関連する問題