12

複数の競合するコンシューマーが分散しており、それぞれが同じ (トランザクション) キューからメッセージを引き出しています。各コンシューマをべき等レシーバとして実装したいので、重複が到着した場合でも、同じメッセージを (すべてのコンシューマにわたって) 2 回以上処理することはありません。複数のコンシューマーでこれを達成するにはどうすればよいですか?

私が最初に考えたのは、各メッセージをキューに入れる前に何らかの方法で連続したシーケンス番号を生成し、共有データベース テーブルを使用してコンシューマー間の作業を調整することです。つまり、consumer#1 は msg#1 を処理し、DB テーブルに「msg#1 が処理されました」という行を書き込みます (耐久性を確保するためにデータベースに入れたい)。コンシューマーは、メッセージを処理する準備ができると、キューで次に使用可能なメッセージを調べ、共有 DB テーブルを調べて、これが次のメッセージであるかどうかを判断します。もしそうなら、それはキューから外されます。そうでない場合、それは無視されます。

このように、処理された最後のメッセージを保存するだけでよく (すべてのメッセージに連続したシーケンス番号があるため)、ネゴシエートされた「ウィンドウ」サイズで受信したすべてのメッセージの ID を保存するバッファーを使用する必要はありません。メッセージは常にシリアルに処理されます (これは、このシナリオで必要なことです)。

より良い方法があるかどうかだけ知りたいですか?メッセージを処理する必要があるときはいつでも、データベースにクエリを実行するコストが心配です。

答えが「フレームワークに依存する」である場合、MSMQ を念頭に置いていました

4

3 に答える 3

9

各メッセージに GUID またはその他の一意の識別子があることを確認し、永続ストアの状態を変更するのと同じトランザクションに記録することで、冪等メッセージを実現しました。

メッセージごとに、永続ストアに一意の ID が存在するかどうかを確認できるようになりました。

一意の ID が存在する場合は、それが以前に処理され、状態の変更が同じトランザクションで保持されていることがわかります。

一意の ID が存在しない場合は、それが処理されていないことがわかります。

2 つのコンシューマーが同じメッセージを処理する場合、処理された一意の ID を格納するテーブルに一意の制約があるため、両方のコンシューマーがトランザクションをコミットするときに、一方が失敗し、すべての変更をロールバックする必要があります。成功した。

于 2018-05-11T21:55:44.470 に答える
3

べき等レシーバのポイントは、メッセージが複数回処理されても問題にならないことです。したがって、冪等の受信者は、メッセージが重複していることを何らかの方法で検出する必要はなく、単に通常どおりに処理できます...

したがって、レシーバーがべき等ではないか、不必要に心配しています...

于 2009-11-03T18:24:59.093 に答える
-2

アンドリュー -

もう 1 つのオプションは、キューがメッセージを処理する方法を確認することです。メッセージがコンシューマによって取得された後にメッセージを削除するキューがあります。これはキューの典型的な動作であり、このタイプの機能を持つキューを見つけるのは難しくありません。これにより、各コンシューマーが別のコンシューマーによって既に処理されたメッセージを受信しないようにする方法を構築する代わりに、単純なソリューションが提供されるはずです。

ベスト、ヘンリー

于 2011-12-23T16:46:19.710 に答える