2

SQSは、アプリケーションがべき等であることを期待しており、複数のコンシューマー/プロデューサーがあります(SQSに1回限りの配信メカニズムがある場合でも)競合状態が重複を作成し、コンシューマーがcronジョブを介して実行されるため競合状態が消費されます。

select_for_update私の現在の計画は、同じ行の他のコンシューマーをブロックするDjango 1.4を使用して、次のようなことを行うことです。

reminders = EmailReminder.objects.select_for_update().filter(id=some_id)
if not reminders[0].finished:
    reminder.send()
    reminder.update(finished=datetime.now())
# Delete job.

これに対処するためのより良い方法はありますか?

4

1 に答える 1

3

django-celeryをSQSに接続し、celerybeatを使用して定期的なジョブを指定するようにします。次に、任意の場所で同じキューでcelerydワーカーを実行します。一度に1人だけがジョブを取得して実行します。どのレベルでもDBロックを導入する必要はありません。

celerybeatが新しいタスクを起動する前に、ワーカーが現在のタスクを完了することが保証されている限り、ロックは必要ありません。これで、重複する可能性があると思われる場合は、通知の状態を次の場所に導入できます。

  1. リマインダーは「未送信」状態で始まります。
  2. celerybeatは、未送信の電子メールを処理する要求をキューに送信します。
  3. 何人かの労働者はそれを拾い上げてそれらすべてをつかみます。
  4. すぐに、ワーカーはそれらすべてを「送信」状態に移行します。
  5. 一度に1つずつ(またはまとめて)送信します。
  6. 送信に失敗した場合は、状態を未送信に戻します。
  7. 送信への移行に成功したすべての場合。

このように、元のジョブが最初のバッチで完了していないときにcelerybeatが別のジョブを起動した場合、重複する電子メールが送信されることはありません。追加のボーナスとして、ソリューションをスケーリングし、負荷を分散させることができます。

于 2012-08-04T22:16:00.310 に答える