web-dev-qa-db-ja.com

重複するイベント処理を防止する

イベントが複数回処理されるのを防ぐ最善の方法は何ですか?

顧客が注文できるシステムを想像してください。そして、成功するとOrderCreatedイベントが発生します。メッセージバスでイベントをリッスンするいくつかの個別のプロセスがあります。

1つのプロセスは、顧客にメールを送信することです。顧客にメールを送信する必要があるという要件があると想定します。

メール送信プロセスは次のように機能すると思います。

  1. メールを送る
  2. 永続的なハンドルID
  3. メッセージバスを確認する

ただし、処理されたIDの保持に失敗した場合、お客様は複数のメールを受け取ります。

私が考えた他の唯一の解決策は、次のことをすることでした:

  1. イベントIDを処理しようとします。
  2. メールを送る
  3. 永続的に処理されるイベントID
  4. メッセージバスを確認する

これにより、イベントを以前に処理しようとしたかどうかを確認できます。そうである場合は、エラーを発生させ、再試行するかどうかを人間に尋ねます。

このような問題を処理するためのより良い方法はありますか?このようなことはよくある問題だと思いますが、堅牢な解決策を見つけることができません。

7
Nick Williams

イベントが複数回処理されるのを防ぐ最善の方法は何ですか?

最善の方法:最大で1回の処理がビジネスロジックに組み込まれるようにドメインモデルを記述します。

Marc de Graauw氏 Nobody Needs Reliable Messaging から:

注文処理のように、すべてのメッセージが正確に一度だけ受信されることがビジネスレベルで重要であると述べることは、すべてのメッセージが一意のビジネストランザクションを構成することを意味します...すべてのメッセージが一意のビジネストランザクションである場合、ビジネスレベルの一意のID ....ビジネスレベルでそのような一意のトークンが必要な場合、ビジネスレベルはその一意性を主張する必要があります。ビジネスレベルの一意性は、メッセージレベルの一時的な一意性に依存するべきではありませんが、ビジネスメッセージの永続的な機能である必要があり、ビジネスセマンティクスはそれを保証する必要があります。

しかし、それはあなたが検討している種類の例ではありません。

1つのプロセスは、顧客にメールを送信することです。顧客にメールを送信する必要があるという要件があると想定します。

しなければならない状況で;私は通常、イベントの少なくとも1回の処理を探します。このプロセスでは、必要なメールと確認済みのメールの両方を追跡します。

たとえば、OrderCreatedEmailSent、およびEmailTimedOutをサブスクライブするプロセスです。 「order created」では、メールを送信するコマンドと、タイムアウトイベントを発行するコマンドをディスパッチします。タイムアウトを受け取ったら、EmailSentメッセージが表示されたかどうかを確認します。表示されていない場合は、resendと表示されます。

このような問題を処理するためのより良い方法はありますか?

さまざまな障害モードのビジネスへのコストを詳細に確認します。メールを送信する必要がある場合は、送信したことを確認するためのackが必要です。 ACKが失われる可能性がある場合は、再送信する必要があります-その電子メールを2回以上送信するビジネスのコストはどれくらいですか?失敗がまれで低コストの場合は、費用のかかる完璧なサービスにサインアップしないでください。

このようなことはよくある問題だと思いますが、堅牢な解決策を見つけることができません。

ジョナサンオリバー: メッセージング:少なくとも1回は配信

メッセージングシステムが正確に1回ではなく少なくとも1回の配信を提供する主な理由ではない場合の主な理由の1つは、CAPの定理に示されているように制限に直面することです。すべての「ノード」がグローバルに一貫性のあるスナップショットを使用し、パーティションを許容します。確実な「グローバル脳」はありません。

参照: https://stackoverflow.com/q/416551/54734

5
VoiceOfUnreason