1

PHP ファイルを実行する 5 つの cron ジョブがあります。PHP ファイルは、MySQL データベースで処理が必要なアイテムをチェックします。cron はスクリプトをすべて同時に起動するため、項目によっては 2 回、場合によっては最大 5 回処理されるようです。

スクリプトの 1 つでファイルを選択すると、すぐに UPDATE クエリが送信されるため、他のジョブがそのファイルを再度実行することはありません。しかし、それはまだ二重処理のようです。

他の cron ジョブによって以前に選択された項目を他のスクリプトが処理しないようにするにはどうすればよいですか?

4

3 に答える 3

4

この問題は「競合状態」と呼ばれます。この場合、SELECT と UPDATE は次々に呼び出されますが、単一の操作ではないために発生します。したがって、2 つのジョブが同じジョブを SELECT し、次に最初に UPDATE を実行し、次に 2 番目に UPDATE を実行する可能性があります。そして、彼らはこの仕事を同時に実行し始めます。

ただし、回避策があります。現在の cron ジョブ ワーカーの ID を含むフィールドをテーブルに追加できます (1 台のマシンですべてを実行する場合は、PID である可能性があります)。ワーカーでは、最初に UPDATE を実行し、ジョブを予約しようとします。

UPDATE jobs 
    SET worker = $PID, status = 'processing' 
    WHERE worker IS NULL AND status = 'awaiting' LIMIT 1

次に、このワーカーのジョブが正常に予約されたことを確認します。

SELECT * FROM jobs WHERE worker = $PID

行が返されなかった場合は、他のワーカーが最初にそれを予約したことを意味します。ステップ 1 からやり直して、別のジョブを取得できます。行が返された場合は、すべての処理を行い、最後に最終的な UPDATE を行います。

UPDATE jobs 
    SET status = 'done', worker = NULL
    WHERE id = $JOB_ID
于 2013-08-03T09:46:16.863 に答える
2

セマフォの使用には典型的な問題があると思います。この記事を見てください:

http://www.re-cycledair.com/php-dark-arts-semaphores

アイデアは、各スクリプトの最初に、同じセマフォを要求し、それが解放されるまで待つことです。次に、DB を選択して更新し、セマフォを解放してプロセスを開始します。これは、別のスクリプトが DB に書き込もうとしている間に、複数のスクリプトが DB を読み取っていないことを確認できる唯一の方法です。

于 2013-08-03T09:47:03.117 に答える
0

私は再び始めます。この一連の思考:

1つのアイテムを処理するのに時間がかかります。約30秒。5 つの cron ジョブがある場合、5 つの項目が 30 秒で処理されます

これは明らかに間違っており、これを念頭に置いてコードを書くべきではありません。

その論理で、なぜ 100 の cron ジョブを作成し、30 秒ごとに 100 を実行しないのでしょうか? 答えてください。あなたのサーバーはRoadRunnerではなく、落ちて失敗するからです。

あなたがすべき

  1. 問題を再考してください。これは 1 と 2 に役立つため、最も重要です。
  2. 30 秒もかからないようにコードを最適化してください。
  3. コードをセグメント化して、各ジョブが一度に 1 つのタスクのみを実行するようにします。これにより、処理が速くなり、この「二重処理」効果が発生しないようになります。

編集

これがサードパーティのサーバー上にあるという新しい知識があっても、私の論理は依然として有効です。制御できない複数の呼び出しを開始しないでください。実際、これはさらに重要です。

彼らが呼び出しで何をしているのかわからない場合、それらがいつ、または処理されるかどうか、正しい順序であることを確認できません。したがって、二重処理が発生しないようにするには、1 回の呼び出しを行うだけです。

技術的な解決策は、彼らが処理時間を改善するか、応答をキャッシュすることですが、それはあなたの状況には関係ないかもしれません.

于 2013-08-03T09:27:32.700 に答える