celerybeatを使用して1分に1回実行するタスクがあります。正常に動作します。ただし、タスクの2つのインスタンスが実行されるため、タスクの実行に1分以上かかる場合があります。これは、物事を台無しにするいくつかの競合状態につながります。
私は自分のタスクを正しく機能するように修正することができます(そしておそらくそうすべきです)が、セロリにこれを確実にするための組み込みの方法があるかどうか知りたいと思いました。私の大雑把なグーグル検索とRTFMは結果をもたらさなかった。
celerybeatを使用して1分に1回実行するタスクがあります。正常に動作します。ただし、タスクの2つのインスタンスが実行されるため、タスクの実行に1分以上かかる場合があります。これは、物事を台無しにするいくつかの競合状態につながります。
私は自分のタスクを正しく機能するように修正することができます(そしておそらくそうすべきです)が、セロリにこれを確実にするための組み込みの方法があるかどうか知りたいと思いました。私の大雑把なグーグル検索とRTFMは結果をもたらさなかった。
memcached のようなものやデータベースだけを使用して、 lock を追加できます。
定期的なタスクの実行に cron スケジュールまたは時間間隔を使用している場合でも、問題は発生します。データベースやキャッシュ、さらにはファイルシステムを使用していつでもロックメカニズムを使用したり、前のタスクから次のタスクをスケジュールしたりすることができますが、最善の方法ではない可能性があります。この質問はおそらくあなたを助けることができます: django celery: how to set task to run at specific interval at programmatically
実行している関数を保持するオブジェクトにクラスフィールドを追加して、そのフィールドを「他の人が働いているかどうか」コントロールとして使用することができます
ロックは、beat または cron のいずれかを使用する良い方法です。
ただし、ビート ジョブはビートの実行時ではなく、ワーカーの開始時に実行されることに注意してください。
これにより、ロックがあっても競合状態になりました。ワーカーがオフで、beat が 10 個のジョブをキューに投入したとします。セロリが4つのプロセスで起動すると、4つすべてがタスクを取得し、私の場合、1つまたは2つが同時にロックを取得および設定します。
解決策 1 は、ロック付きの cron を使用することです。cron はワーカーの開始時ではなく、その時点で実行されるためです。
解決策 2 は、競合状態を処理するもう少し高度なロック メカニズムを使用することです。redis については、 setnx、または新しいredlockを調べてください。このブログ投稿は非常に優れており、redis-py のロック メカニズムを使用するデコレータ パターンが含まれています: http://loose-bits.com/2010/10/distributed-task-locking-in-celery.html。