剖析 Laravel 计划任务--避免重复
译文GitHub https://github.com/yuansir/diving-laravel-...
原文链接 https://divinglaravel.com/task-scheduling/...
有时一个预定的工作需要比我们最初预期的更多的时间运行,这样会导致另外一个工作的实例开始,而第一个还没有完成,例如,我们运行一个每分钟生成报告的工作有时候当数据变大时,报表生成可能需要1分钟以上,这样就可以在第一个还在进行时启动该作业的另一个实例。
在大多数情况下,这是很好的,但有时候应该防止这种情况,以保证正确的数据或防止高的服务器资源消耗,所以让我们看看如何防止这种情况在laravel中发生:
$schedule->command('mail:send')->withoutOverlapping();
Laravel将检查 Console\Scheduling\Event::withoutOverlapping
类属性,如果设置为true,它将尝试为作业创建互斥,并且只有在创建互斥的情况下才能运行该作业。
但是上面是互斥?
这是我可以在网上找到最有趣的解释:
当我在工作中进行热烈的讨论时,我使用一只橡胶鸡,我在这样的场合放在桌子上。 持有鸡的人是唯一被允许谈话的人。 如果你不握鸡,你不会说话。 你只能指示你想要鸡,等到你说话之前才能得到它。 一旦你完成演讲,你可以将鸡回到主持人,他将把它交给下一个人说话。 这样可以确保人们互不说话,也有自己的空间。 用线替换鸡与互斥和人,你基本上有一个互斥的概念。
所以当作业第一次启动时,Laravel创建一个互斥,然后每次作业运行时,它检查互斥是否存在,只有在没有工作的情况下运行。
这里是 withoutOverlapping
方法中做的事
public function withoutOverlapping()
{
$this->withoutOverlapping = true;
return $this->then(function () {
$this->mutex->forget($this);
})->skip(function () {
return $this->mutex->exists($this);
});
}
因此,Laravel创建一个filter-callback方法,指示Schedule Manager忽略任务,如果互斥仍然存在,它还会创建一个在完成任务实例后清除互斥的回调。
在运行该作业之前,Laravel会在Console\Scheduling\Event::run()
方法中进行以下检查:
if ($this->withoutOverlapping && ! $this->mutex->create($this)) {
return;
}
互斥体属性来自哪里?
当 Console\Scheduling\Schedule
的实例被实例化时,laravel会检查 Console\Scheduling\Mutex
接口的实现是否绑定到容器,如果是,则使用该实例,如果不是,使用Console\Scheduling\CacheMutex
实例:
$this->mutex = $container->bound(Mutex::class)
? $container->make(Mutex::class)
: $container->make(CacheMutex::class);
现在,Schedule Manager正在注册你的事件,它会传递互斥的一个实例:
$this->events[] = new Event($this->mutex, $command);
默认情况下,Laravel使用基于缓存的互斥,但您可以覆盖它并实现自己的互斥方法并将其绑定到容器。
基于缓存的互斥
CacheMutex
类包含3个简单的方法,它使用事件互斥名作为缓存键:
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());
}
任务完成后的互斥删除
如前所述,管理器注册一个在完成任务之后删除互斥的回调,对于在操作系统上运行命令的任务可能足以确保互斥被清除,但是对于回调 执行回调时脚本可能会死机,所以为了防止这种情况在 Console\Scheduling\CallbackEvent::run()
中添加了一个额外的回退:
register_shutdown_function(function () {
$this->removeMutex();
});
转载请注明: 转载自Ryan是菜鸟 | LNMP技术栈笔记
如果觉得本篇文章对您十分有益,何不 打赏一下
本文链接地址: 剖析Laravel计划任务--避免重复
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: