スケジュールされたタスクの実行には想像よりも時間がかかることがあり、問題が発生する可能性があります---現時点ではタスクが完了する前を実行すると、別の同一のタスクが実行され、タスクの重複が発生します。 たとえば、1分ごとにレポートを生成するタスクを実行すると、時間が経つとデータ量が多くなり実行時間が1分を超え、前のタスクよりも先に別のタスクが生成されてしまいます。タスクが完了し、同じタスクの実行が開始されます。
ほとんどの場合、問題はありませんが、正しいデータを確保するためにこの状況を回避する必要がある場合があります。 Laravel では、withoutOverlapping
メソッドを通じてこれを処理できます。
$schedule->command('mail:send')->withoutOverlapping();
Laravel は、Console\Scheduling\Event::withoutOverlapping
属性をチェックし、値が true の場合、このタスク用にミューテックスが作成され、タスクはミューテックスを作成できる場合にのみ実行されます。
これは私がオンラインで見つけた最も面白い説明です:
会議に参加して白熱した議論をしているとき、私は机からスクリーミング チキンを取り出します。スクリーミングチキンを持っている人だけが話すことができ、スクリーミングチキンを持っていないと話すことができません。会議の主催者に指示を求めることしかできず、スクリーミング チキンを手に入れたときにのみ話すことができ、それ以外の場合は待つことしかできません。話し終えたら、スクリーミング チキンを会議の主催者に返します。主催者は、次に話す人にスクリーミング チキンを渡します。これにより、人々がお互いに話し合うことがなくなり、自分の話す時間を確保できるようになります。
叫ぶニワトリをミューテックス ロックに、人物をスレッドに置き換えます。基本的に、ミューテックスの基本概念は理解できています。
-- https://stackoverflow.com/questions/34524/...
Laravel が初めてタスクを実行するミューテックスロックが作成され、タスクを実行するたびにミューテックスロックが存在するかどうかがチェックされ、ミューテックスロックが存在しない場合にのみタスクが実行されます。 withoutOverlapping
メソッドは次のとおりです:
public function withoutOverlapping() { $this->withoutOverlapping = true; return $this->then(function () { $this->mutex->forget($this); })->skip(function () { return $this->mutex->exists($this); }); }
Laravel は、ミューテックスがまだ存在するタスクを無視するようにスケジュール マネージャーに指示するフィルター コールバック メソッドを作成し、完了後にクリーンアップするメソッドも作成します。タスク インスタンスのミューテックス コールバック。同時に、タスクを実行する前に、Lravel は Console\Scheduling\Event::run()
メソッドで次の一連のチェックを実行します。ミューテックスはどこから来たのですか?
Console\Scheduling\Schedule
がインスタンス化されると、Laravel はConsole\Scheduling\Mutex がコンテナにバインドされているかどうかを確認し、バインドされている場合はインスタンス化されます。変更しないと、
Console\Scheduling\CacheMutex
if ($this->withoutOverlapping && ! $this->mutex->create($this)) { return; }
が使用されます。タスク マネージャーがイベントを登録すると、ミューテックス インスタンスも一緒に渡されます:
$this->mutex = $container->bound(Mutex::class) ? $container->make(Mutex::class) : $container->make(CacheMutex::class);
$this->events[] = new Event($this->mutex, $command);
Laravel チュートリアル コラムを参照して学習してください。
以上がLaravel がスケジュールされたタスクの繰り返し実行を防ぐ方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。