Manchmal kann die Ausführung einer geplanten Aufgabe länger dauern, als wir denken, was zu Problemen führt——Derzeit Bevor die Aufgabe abgeschlossen ist , wird eine weitere identische Aufgabe ausgeführt, was zu einer Duplizierung der Aufgabe führt. Stellen Sie sich zum Beispiel vor, dass wir eine Aufgabe ausführen, die jede Minute einen Bericht generiert. Nach einer gewissen Zeit wird die Datenmenge so groß, dass die Ausführungszeit 1 Minute überschreitet Die vorherige Aufgabe ist abgeschlossen. Die Ausführung derselben Aufgabe beginnt.
In den meisten Fällen gibt es kein Problem, aber manchmal müssen wir diese Situation vermeiden, um sicherzustellen, dass wir die richtigen Daten erhalten. In Laravel können wir das über die withoutOverlapping
-Methode handhaben:
$schedule->command('mail:send')->withoutOverlapping();
Laravel prüft das ConsoleSchedulingEvent::withoutOverlapping
-Attribut. Wenn der Wert wahr ist, wird ein Mutex für diese Aufgabe erstellt, und diese Aufgabe wird nur wahr sein wird durchgeführt, wenn der Mutex erstellt werden kann.
Das ist die lustigste Erklärung, die ich online gefunden habe:
Wenn wir in einer Besprechung sind und eine hitzige Diskussion führen, hole ich ein schreiendes Huhn aus meinem Schreibtisch. Nur die Person, die das Schreiende Huhn hält, kann sprechen. Wenn Sie das Schreiende Huhn nicht halten, können Sie nicht sprechen. Sie können den Gastgeber des Meetings nur um Anweisungen bitten und nur sprechen, wenn Sie das schreiende Huhn erhalten, andernfalls können Sie nur warten. Wenn Sie mit dem Sprechen fertig sind, geben Sie das Schreiende Huhn an den Gastgeber des Meetings zurück, der das Schreiende Huhn an die nächste Person weitergibt, die sprechen soll. Dadurch wird sichergestellt, dass die Leute nicht übereinander reden, sondern auch, dass sie ihre eigene Zeit zum Reden haben.
Ersetzen Sie das schreiende Huhn durch eine Mutex-Sperre und die Menschen durch Threads. Sie haben im Grunde das Grundkonzept einer Mutex-Sperre.
-- https://stackoverflow.com/questions/34524/...
Laravel führt die Aufgabe zum ersten Mal aus Zeit Es wird eine Mutex-Sperre erstellt und bei jeder Ausführung einer Aufgabe überprüft, ob die Mutex-Sperre vorhanden ist. Die Aufgabe wird nur ausgeführt, wenn die Mutex-Sperre nicht vorhanden ist. Hier ist die withoutOverlapping
-Methode:
public function withoutOverlapping() { $this->withoutOverlapping = true; return $this->then(function () { $this->mutex->forget($this); })->skip(function () { return $this->mutex->exists($this); }); }
Laravel erstellt eine Filter-Rückrufmethode, um den Zeitplanmanager anzuweisen, Aufgaben zu ignorieren, für die der Mutex noch vorhanden ist, und erstellt außerdem einen Rückruf, der den Mutex nach Abschluss der Aufgabeninstanz löscht . Rückruf. Gleichzeitig führt Lravel vor der Ausführung der Aufgabe die folgende Reihe von Prüfungen in der ConsoleSchedulingEvent::run()
-Methode durch:
if ($this->withoutOverlapping && ! $this->mutex->create($this)) { return; }
Woher kommen also die Eigenschaften der Mutex-Sperre?
Wenn ConsoleSchedulingSchedule
instanziiert wird, prüft Laravel, ob ConsoleSchedulingMutex
an den Container gebunden ist. Wenn ja, wird es instanziiert, andernfalls wird ConsoleSchedulingCacheMutex
$this->mutex = $container->bound(Mutex::class) ? $container->make(Mutex::class) : $container->make(CacheMutex::class);
verwendet Wenn der Task-Manager ein Ereignis registriert, wird es in der Mutex-Instanz übergeben:
$this->events[] = new Event($this->mutex, $command);
Laravel verwendet standardmäßig einen im Cache implementierten Mutex, aber Sie können ihn selbst implementieren und ersetzen.
Die CacheMutex-Klasse verfügt nur über drei einfache Methoden, die den Namen des Ereignis-Mutex als Cache-Schlüssel verwenden:
public function create(Event $event) { return $this->cache->add($event->mutexName(), true, 1440); } public function exists(Event $event) { return $this->cache->has($event->mutexName()); } public function forget(Event $event) { $this->cache->forget($event->mutexName()); }
Genau wie wir gesehen haben Zuvor registriert der Manager einen Rückruf nach der Ausführung, um sicherzustellen, dass der Mutex entfernt wird, wenn die Aufgabe abgeschlossen ist. Für einen Befehl im System kann bereits garantiert werden, dass er entfernt wird. Bei einer Aufgabe mit einer Rückrufmethode wird das Skript jedoch möglicherweise beendet, wenn der Rückruf ausgeführt wird. Um diese Situation zu vermeiden, wird daher der folgende Code zur ConsoleSchedulingCallbackEvent::run()
-Methode hinzugefügt, um sicherzustellen, dass die Mutex-Sperre normal entfernt werden kann wenn die Aufgabe unerwartet geschlossen wird:
register_shutdown_function(function () { $this->removeMutex(); });
Weitere technische Artikel zu Laravel finden Sie in der Spalte Laravel-Tutorial, um mehr zu erfahren!
Das obige ist der detaillierte Inhalt vonWie Laravel verhindert, dass Ihre geplanten Aufgaben wiederholt ausgeführt werden. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!