>  기사  >  PHP 프레임워크  >  Laravel이 예약된 작업이 반복적으로 실행되는 것을 방지하는 방법

Laravel이 예약된 작업이 반복적으로 실행되는 것을 방지하는 방법

步履不停
步履不停원래의
2019-07-03 14:37:423335검색

Laravel이 예약된 작업이 반복적으로 실행되는 것을 방지하는 방법

기본 소개

때때로 예정된 작업의 실행이 생각보다 오래 걸려 문제가 발생할 수 있습니다 ——#🎜🎜 #현재 작업이 완료되지 않은 경우 동일한 작업이 또 실행되어 작업이 중복됩니다. 예를 들어 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은 다음과 같이 캐시 구현 뮤텍스를 사용합니다. 기본값이지만 직접 구현하고 교체할 수 있습니다. #🎜🎜#

뮤텍스의 캐시 버전

#🎜🎜#CacheMutex 클래스에는 이벤트 뮤텍스 이름을 캐시 키로 사용하는 3가지 간단한 메서드만 있습니다. #🎜🎜#rrreee #🎜🎜# 이전에 살펴본 것처럼 관리자는 작업이 완료될 때 뮤텍스가 제거되도록 보장하기 위해 실행 후 콜백을 등록합니다. 시스템의 명령에 대해서는 이미 제거가 보장될 수 있습니다. 단, 콜백 메서드 작업의 경우 콜백 실행 시 스크립트가 종료될 수 있으므로 이러한 상황을 방지하기 위해 ConsoleSchedulingCallbackEvent::run() 메서드에 다음 코드를 추가하여 보장합니다. 뮤텍스 잠금이 설정되어 있습니다. 작업이 예기치 않게 종료되면 정상적으로 제거될 수 있습니다: #🎜🎜#rrreee#🎜🎜#더 많은 Laravel 관련 기술 기사를 보려면 #🎜🎜#Laravel Tutorial#🎜🎜# 열을 방문하여 알아보세요. ! #🎜🎜#

위 내용은 Laravel이 예약된 작업이 반복적으로 실행되는 것을 방지하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
이전 기사:Laravel 문서화 도구다음 기사:Laravel 문서화 도구