Laravel 定时任务,避免重复的方法-----使用文件锁
1

有时一个预定的工作需要比我们最初预期的更多的时间运行,这样会导致另外一个工作的实例开始,而第一个还没有完成,例如,我们运行一个每分钟生成报告的工作有时候当数据变大时,报表生成可能需要 1 分钟以上,这样就可以在第一个还在进行时启动该作业的另一个实例。

在大多数情况下,这是很好的,但有时候应该防止这种情况,以保证正确的数据或防止高的服务器资源消耗,所以让我们看看如何防止这种情况在 laravel 中发生: $schedule->command('mail:send')->withoutOverlapping(); Laravel 将检查 Console\Scheduling\Event::withoutOverlapping 类属性,如果设置为 true,它将尝试为作业创建互斥,并且只有在创建互斥的情况下才能运行该作业。 但是上面是互斥?这是我可以在网上找到最有趣的解释: 当我在工作中进行热烈的讨论时,我使用一只橡胶鸡,我在这样的场合放在桌子上。 持有鸡的人是唯一被允许谈话的人。 如果你不握鸡,你不会说话。 你只能指示你想要鸡,等到你说话之前才能得到它。 一旦你完成演讲,你可以将鸡回到主持人,他将把它交给下一个人说话。 这样可以确保人们互不说话,也有自己的空间。 用线替换鸡与互斥和人,你基本上有一个互斥的概念。 –https://stackoverflow.com/questions/34524/what-is-a-mutex/34558#34558 所以当作业第一次启动时,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();
});``

致力于成为laravel布道者

《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 3
Complicated

这种问题之前也遇到过,我的办法比较粗暴,在库里有个配置项,定时任务一起来就去检查这个配置项 true就执行作业,false就直接结束定时任务。当一个定时实例开始,就把这个配置项改成false,结束的时候改成true。这样还是会起实例,但是任务不会重复执行

1个月前
等车的猪

@Complicated 使用withoutOverlapping就好了,内部实现了文件锁

1个月前

格式完全乱了

1个月前

  • 请注意单词拼写,以及中英文排版,参考此页
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
  • 支持表情,使用方法请见 Emoji 自动补全来咯,可用的 Emoji 请见 :metal: :point_right: Emoji 列表 :star: :sparkles:
  • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif
  • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
  请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!