データベースに多数のフィード オブジェクトがあり、各フィードを 1 時間ごとに更新しようとしています。ここでの問題は、重複した更新がないことを確認する必要があることです。1 時間に 1 回しか発生しないようにする必要がありますが、フィードが更新のために 2 時間待機することも望ましくありません。(1 時間 +/- 数分ごとに発生する場合は問題ありませんが、数分に 2 回発生するのは問題です。)
私は Django と Celery を Amazon SQS と共にブローカーとして使用しています。Celery タスクとしてフィード更新コードをセットアップしましたが、複数のノードで実行されている Celery との互換性を維持しながら、重複を防ぐ方法を見つけることができません。
私の現在の解決策は、Feed モデルに属性を追加し、last_update_scheduled
5 分ごとに次のタスクを実行することです (疑似コード)。
threshold = datetime.now() - timedelta(seconds=3600)
for f in Feed.objects.filter(Q(last_update_scheduled__lt = threshold) |
Q(last_update_scheduled = None)):
updateFeed.delay(f)
f.last_update_scheduled = now
f.save()
これは、多くの同期の問題の影響を受けやすくなっています。たとえば、タスク キューがバックアップされると、このタスクが同時に 2 回実行され、更新が重複する可能性があります。これに対するいくつかの解決策を見てきました ( Celery のレシピやStack Overflow の適応など) が、memcached の解決策は信頼できません。言うまでもなく、単純なロックのためだけに memcached を本番構成に追加する必要はありません。
完璧な世界では、次のように言えるようになりたいです。
@modelTask(Feed, run_every=3600)
def updateFeed(feed):
# do something expensive
しかし、これまでのところ、そのデコレータを実装する方法について私の想像力は失敗しています。