web-dev-qa-db-ja.com

SQSメッセージの重複を防ぐ方法

Amazon SQSでメッセージの重複を防ぐ最良の方法は何ですか?クロールを待機しているドメインのSQSがあります。 SQSに新しいドメインを追加する前に、保存されたデータをチェックして、最近クロールされたかどうかを確認し、重複を防ぎます。

問題は、まだクロールされていないドメインにあります。たとえば、キュ​​ーにクロールされていないドメインが1000個ある場合。これらのリンクはどれも何度も何度も追加できます。これにより、SQSが数十万のメッセージに膨れ上がり、ほとんどが重複しています。

これを防ぐにはどうすればよいですか?キューからすべての重複を削除する方法はありますか?または、追加する前にキューでメッセージを検索する方法はありますか?これは、SQSを持っている人なら誰でも経験したはずの問題だと思います。

私が見ることができる1つのオプションは、ドメインがSQSに追加される前にデータを保存するかどうかです。しかし、データを2回保存しなければならない場合、そもそもSQSを使用するポイントが台無しになります。

35
Marcus Lind

他の回答で述べたように、SQSから重複メッセージが送信されるのを防ぐことはできません。

ほとんどの場合、メッセージは消費者の1人に1回渡されますが、ある段階で重複することになります。

この質問には簡単な答えはないと思います。重複に対処できる適切なアーキテクチャを考え出す必要があるからです。つまり、本質的にi等であるということです。

分散アーキテクチャのすべてのワーカーがべき等である場合、重複を心配する必要がないため、簡単になります。しかし実際には、そのような環境は存在せず、何かがそれを処理できない途中のどこかにあります。

私は現在、これを解決する必要があるプロジェクトに取り組んでおり、それを処理するアプローチを考え出します。ここで自分の考えを共有することは、他の人にとっても有益だと思いました。そして、私の考えについてのフィードバックを得るのに良い場所かもしれません。

ファクトストア

影響を受けるすべてのダウンストリームシステムで同じ状態を再現するために理論的に再生できるファクトを収集するようにサービスを開発することは非常に良い考えです。

たとえば、株式取引プラットフォーム用のメッセージブローカーを構築しているとします。 (以前にこのようなプロジェクトに取り組んだことがありますが、それは恐ろしいものでしたが、良い学習経験でもありました。

今、その取引が入ってくるとしましょう。それに興味がある3つのシステムがあります。

  1. 最新の状態を維持する必要がある古い学校のメインフレーム
  2. すべての取引を照合し、FTPサーバー上のパートナーと共有するシステム
  3. 取引を記録し、新しい所有者に株式を再割り当てするサービス

少し複雑ですが、1つのメッセージ(事実)が入ってくると、さまざまなダウンストリームの分散効果があるという考えです。

ここで、ブローカーに入ってくるすべての取引の記録であるファクトストアを維持していると想像してみましょう。そして、3人のダウンストリームサービス所有者全員が、過去3日間ですべてのデータを失ったことを伝えるために私たちに電話すること。 FTPダウンロードは3日遅れ、メインフレームは3日遅れ、すべての取引は3日遅れています。

ファクトストアがあるため、理論的には特定の時間から特定の時間までこれらすべてのメッセージを再生できます。この例では、3日前から現在までです。そして、下流のサービスが追いつく可能性があります。

この例は少し上に見えるかもしれませんが、私は非常に特別なことを伝えようとしています:事実は追跡するべき重要なものです。

ファクトストアがメッセージの重複にどのように役立つか

CAP定理 、一貫性および可用性のCA部分を提供する永続層にファクトストアを実装する場合、以下を実行できます。

メッセージがキューから受信されるとすぐに、ファクトストアで、このメッセージを以前に表示したことがあるかどうか、また、もしあれば、その時点でロックされて保留状態になっているかどうかを確認します。私の場合、MongoDBを使用してファクトストアを実装しますが、これには非常に満足していますが、他のさまざまなDBテクノロジーがこれを処理できるはずです。

ファクトがまだ存在しない場合、保留状態とロック有効期限とともにファクトストアに挿入されます。これは、アトミック操作を使用して実行する必要があります。これは、これを2回実行したくないためです。ここで、サービスの idempotence を確認します。

幸せな場合-ほとんどの場合に発生します

ファクトストアがサービスに戻って、ファクトが存在せず、ロックが作成されたことを伝えると、サービスはその作業を試みます。完了すると、SQSメッセージを削除し、ファクトに完了のマークを付けます。

重複メッセージ

そのため、メッセージが送信されたときにそれが起こり、重複ではありません。しかし、重複したメッセージがいつ届くかを見てみましょう。サービスはそれをピックアップし、ファクトストアにロックで記録するように要求します。ファクトストアは、それが既に存在し、ロックされていることを伝えます。サービスはメッセージを無視してスキップします!他のワーカーによってメッセージ処理が完了すると、キューからこのメッセージが削除され、再び表示されることはありません。

災害の場合-めったに起こりません

それでは、サービスがストアで初めてファクトを記録し、その後一定期間ロックを取得しても、倒れるとどうなりますか? SQSは、メッセージが受信された場合でも、キューから提供されてから一定期間内に削除されない場合、メッセージを再度表示します。そのため、サービスが一定期間ロックを維持するようにファクトストアをコーディングします。倒れた場合、SQSがメッセージをサービスまたはその別のインスタンスに後で提示し、そのサービスが事実を再び状態に組み込む(実行する)ことを想定できるようにするためです。

39
hendrikswan

重複メッセージがSQSキューに送信されるのを防ぐAPIレベルの方法はありません。あなたは私が恐れているアプリケーションレベルでこれを処理する必要があります。

DynamoDBテーブルを使用して、クロールを待機しているドメイン名を保存し、たとえば、DynamoDBにない場合にのみキューに追加できます。

4

AWS Docsによると、Exactly-Once Processingは、メッセージの重複を回避する方法を提供します。

標準のキューとは異なり、FIFOキューは重複したメッセージを導入しません。FIFOキューは重複したキューへの送信を回避するのに役立ちます。 5分の重複排除間隔、Amazon SQSはキューに重複を導入しません。

キューがFIFOキューであり、コンテンツベースの複製が有効になっている場合、この機能を使用して、重複排除間隔中のメッセージの重複を回避できます。詳細は、 section 、および以下のリンク。

https://docs.aws.Amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-sqs-queues.html#cfn-sqs-queue-contentbaseddeduplication

3

SQSが重複したメッセージを送信するのを防ぐことはできないため、これをユーザー側で実装する必要があります。これを行う1つの簡単な方法は、Apache Camelのべき等消費者を使用することです。 http://camel.Apache.org/idempotent-consumer.html を参照してください。

2
faermanj