때때로 예정된 작업의 실행이 생각보다 오래 걸려 문제가 발생할 수 있습니다 ——#🎜🎜 #현재 작업이 완료되지 않은 경우 동일한 작업이 또 실행되어 작업이 중복됩니다. 예를 들어 1분마다 보고서를 생성하는 작업을 실행한다고 가정해 보겠습니다. 일정 시간이 지나면 데이터 양이 많아지고 실행 시간이 1분을 초과하게 됩니다. 이전 작업이 완료되었습니다. 동일한 작업이 실행을 시작합니다.
Solution대부분의 경우 문제가 없지만 때로는 올바른 데이터를 얻기 위해 이러한 상황을 피해야 할 때도 있습니다. Laravel에서는withoutOverlapping
메소드를 통해 이를 처리할 수 있습니다:
$schedule->command('mail:send')->withoutOverlapping();
withoutOverlapping
方法来进行处理:public function withoutOverlapping() { $this->withoutOverlapping = true; return $this->then(function () { $this->mutex->forget($this); })->skip(function () { return $this->mutex->exists($this); }); }
Laravel会检查ConsoleSchedulingEvent::withoutOverlapping
属性,如果该值为true那么将会针对这个任务创建一个互斥锁(mutex),并且只有在可以创建互斥锁的情况下才会执行此任务。
这是我在网上找到的最有趣的解释:
当我们在开会进行激烈的讨论时,我会从我桌子里拿出来一个尖叫鸡。只有手里拿着尖叫鸡的人才能说话,如果你没有拿着尖叫鸡你是不能说话的。你只能向会议主持人请示,只有在你拿到尖叫鸡的时候你才能说话否则只能等待。当你讲话完毕的时候,将尖叫鸡还给会议主持人,主持人会将尖叫鸡给到下一个人来让其说话。这样会确保人们不会互相交谈,同时他们也会有自己的时间来进行讲话。
将尖叫鸡换成互斥锁,人换成线程。你基本上就有了一个互斥锁的基本概念。
-- https://stackoverflow.com/questions/34524/...
Laravel在第一次执行任务的时候会创建一个互斥锁,然后在每次执行任务时会检查互斥锁是否存在,只有互斥锁不存在的时候任务才会执行。下面是withoutOverlapping
方法:
if ($this->withoutOverlapping && ! $this->mutex->create($this)) { return; }
Laravel创建了一个过滤回调方法来告诉计划管理器忽略互斥锁仍然存在的任务,同时也创建了一个在完成任务实例后清除互斥锁的回调。同时,在执行任务之前,Lravel会在ConsoleSchedulingEvent::run()
方法中依次执行下面一系列的检查:
$this->mutex = $container->bound(Mutex::class) ? $container->make(Mutex::class) : $container->make(CacheMutex::class);
那么互斥锁的属性是从哪里来的呢?
当ConsoleSchedulingSchedule
被实例化的时候,Laravel会检查ConsoleSchedulingMutex
是否绑定到了容器,如果是那么就会实例化它,否则会使用ConsoleSchedulingCacheMutex
$this->events[] = new Event($this->mutex, $command);
现在当任务管理器在注册事件的时候会将互斥锁的实例一并传进去:
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()); }
Laravel默认使用了缓存实现的互斥锁,但是你可以自己实现并替换它。
CacheMutex类只有3个简单的方法,它使用了事件互斥锁的名字作为缓存的键值:
register_shutdown_function(function () { $this->removeMutex(); });
就像我们之前看过的,管理器注册了一个执行后回调来保证任务执行完毕的时候移除互斥锁,对于一个系统里的命令来说也许已经可以确保移除了。但是对于一个回调方法的任务来说脚本可能在执行回调的时候结束,因此为了避免这种情况在ConsoleSchedulingCallbackEvent::run()
Laravel은 ConsoleSchedulingEvent::withoutOverlapping
속성을 확인하고, 값이 true이면 이 작업에 대해 뮤텍스가 생성되며, 뮤텍스를 생성할 수 있는 경우에만 작업이 실행됩니다.
뮤텍스 잠금이란 무엇인가요? 온라인에서 찾은 설명 중 가장 웃긴 설명입니다.
#🎜🎜#회의 중 열띤 토론을 할 때 책상에서 하나를 꺼냅니다. 비명을 지르는 닭. 소리 지르는 닭을 들고 있는 사람만이 말할 수 있고, 소리 지르는 닭을 들고 있지 않으면 말을 할 수 없습니다. 회의 진행자에게 지시만 요청할 수 있고, 비명치킨을 얻었을 때만 말할 수 있고, 그렇지 않으면 기다릴 수만 있습니다. 발언이 끝나면 비명을 지르는 치킨을 회의 주최자에게 돌려주십시오. 그러면 회의 주최자는 다음으로 발언할 사람에게 비명을 지르는 치킨을 줄 것입니다. 이렇게 하면 사람들이 서로 대화를 나누지 않고 자신만의 시간을 갖게 됩니다. #🎜🎜##🎜🎜#소리 지르는 닭을 뮤텍스 잠금으로 바꾸고 사람을 스레드로 바꿉니다. 기본적으로 뮤텍스의 기본 개념이 있습니다. #🎜🎜##🎜🎜#-- https://stackoverflow .com/questions/34524/...#🎜🎜##🎜🎜##🎜🎜#Principle Analysis#🎜🎜##🎜🎜#Laravel은 작업을 처음 실행할 때 뮤텍스 잠금을 생성하고 그 다음에는 매번 작업이 실행될 때 뮤텍스 잠금이 존재하는지 확인합니다. 뮤텍스 잠금이 존재하지 않는 경우에만 작업이 실행됩니다. 다음은
withoutOverlapping
메서드입니다. #🎜🎜#rrreee#🎜🎜#Laravel은 필터 콜백 메서드를 생성하여 일정 관리자에게 뮤텍스가 여전히 존재하는 작업을 무시하도록 지시하고, 인스턴스 후에 뮤텍스를 지우는 콜백이 여전히 존재합니다. 동시에, 작업을 실행하기 전에 Lravel은 ConsoleSchedulingEvent::run()
메서드에서 다음과 같은 일련의 검사를 수행합니다: #🎜🎜#rrreee#🎜🎜#그런 다음 뮤텍스의 속성 그것은 어디에서 왔는가? #🎜🎜##🎜🎜#ConsoleSchedulingSchedule
이 인스턴스화되면 Laravel은 ConsoleSchedulingMutex
가 컨테이너에 바인딩되어 있는지 확인하고, 그렇지 않으면 를 사용합니다. code>ConsoleSchedulingCacheMutex
#🎜🎜#rrreee#🎜🎜#이제 작업 관리자가 이벤트를 등록할 때 뮤텍스 인스턴스를 함께 전달합니다. #🎜🎜#rrreee#🎜🎜# Laravel은 다음과 같이 캐시 구현 뮤텍스를 사용합니다. 기본값이지만 직접 구현하고 교체할 수 있습니다. #🎜🎜#ConsoleSchedulingCallbackEvent::run()
메서드에 다음 코드를 추가하여 보장합니다. 뮤텍스 잠금이 설정되어 있습니다. 작업이 예기치 않게 종료되면 정상적으로 제거될 수 있습니다: #🎜🎜#rrreee#🎜🎜#더 많은 Laravel 관련 기술 기사를 보려면 #🎜🎜#Laravel Tutorial#🎜🎜# 열을 방문하여 알아보세요. ! #🎜🎜#위 내용은 Laravel이 예약된 작업이 반복적으로 실행되는 것을 방지하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!