Laravel是怎样防止你的定时任务重复执行的
基本介绍
有时候一个定时任务执行需要的时间可能会比我们想象的要长,这就会引起一个问题——当前任务还没有执行完毕的时候另一个相同的任务也会执行,从而导致任务重复。例如想象一下我们执行每分钟生成一次报告的任务,在经过一段时间后,数据量变得很大导致执行时间多于1分钟,这样就会导致在上一个任务还没结束的时候另一个相同的任务开始执行。
解决方法
大部分情况下是没有什么问题的,但是有时我们需要避免这种情况来保证获得正确的数据。在Laravel中我们可以通过withoutOverlapping
方法来进行处理
$schedule->command('mail:send')->withoutOverlapping();
Laravel会检查Console\Scheduling\Event::withoutOverlapping
属性,如果该值为true那么将会针对这个任务创建一个互斥锁(mutex),并且只有在可以创建互斥锁的情况下才会执行此任务。
什么是互斥锁?
这是我在网上找到的最有趣的解释:
当我们在开会进行激烈的讨论时,我会从我桌子里拿出来一个尖叫鸡。只有手里拿着尖叫鸡的人才能说话,如果你没有拿着尖叫鸡你是不能说话的。你只能向会议主持人请示,只有在你拿到尖叫鸡的时候你才能说话否则只能等待。当你讲话完毕的时候,将尖叫鸡还给会议主持人,主持人会将尖叫鸡给到下一个人来让其说话。这样会确保人们不会互相交谈,同时他们也会有自己的时间来进行讲话。
将尖叫鸡换成互斥锁,人换成线程。你基本上就有了一个互斥锁的基本概念。
链接:https://pan.baidu.com/s/1v5gm7n0L7TGyejCmQrMh2g 提取码:x2p5
免费分享,但是X度限制严重,如若链接失效点击链接或搜索加群 群号518475424。
原理分析
Laravel在第一次执行任务的时候会创建一个互斥锁,然后在每次执行任务时会检查互斥锁是否存在,只有互斥锁不存在的时候任务才会执行。下面是withoutOverlapping
方法:
public function withoutOverlapping() { $this->withoutOverlapping = true; return $this->then(function () { $this->mutex->forget($this); })->skip(function () { return $this->mutex->exists($this); }); }
Laravel创建了一个过滤回调方法来告诉计划管理器忽略互斥锁仍然存在的任务,同时也创建了一个在完成任务实例后清除互斥锁的回调。同时,在执行任务之前,Lravel会在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);
现在当任务管理器在注册事件的时候会将互斥锁的实例一并传进去:
$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是怎样防止你的定时任务重复执行的的更多相关文章
- springBoot框架分布式部署定时任务重复执行之解决方案
问题描述: 在集群模式部署服务端时,会出现所有的定时任务在各自的节点处均会执行一遍,这显然不符合实际的开发场景,针对这种问题,本文给出一种springboot集成shedlock的解决方案 第一步:引 ...
- flock防止crontab脚本周期内未执行完重复执行(转)
如果某脚本要运行30分钟,可以在Crontab里把脚本间隔设为至少一小时来避免冲突.而比较糟的情况是可能该脚本在执行周期内没有完成,接着第二个脚本又开始运行了.如何确保只有一个脚本实例运行呢?一个好用 ...
- Celery异步任务重复执行(Redis as broker)
之前讲到利用celery异步处理一些耗时或者耗资源的任务,但是近来分析数据的时候发现一个奇怪的现象,即是某些数据重复了,自然想到是异步任务重复执行了. 查阅之后发现,到如果一个任务太耗时,任务完成时间 ...
- Spring+quartz集群解决多服务器部署定时器重复执行的问题
一.问题描述 Spring自带的Task虽然能很好使用定时任务,只需要做些简单的配置就可以了.不过如果部署在多台服务器上的时候,这样定时任务会在每台服务器都会执行,造成重复执行. 二.解决方案 Spr ...
- 如何解决 shell 脚本重复执行的问题
在开发过程中,经常会使用shell脚本去完成定时备份的任务,普遍的做法是通过系统的定时任务定时执行备份脚本 设想这样一种场景,本次备份时间到了,自动执行备份脚本,如果备份比较耗时的话,会一直持续到下一 ...
- 测试平台系列(82) 解决APScheduler重复执行的问题
大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的完整教程,希望大家多多支持. 欢迎关注我的公众号测试开发坑货,获取最新文章教程! 回顾 上一节我们编写了在线执行R ...
- remove name="ProxyModule“会导致重复执行
<?xml version="1.0" encoding="utf-8"?> <!-- 有关如何配置 ASP.NET 应用程序的详细信息,请访 ...
- jquery 实现重复点击一个元素时不重复执行效果
jquery 实现重复点击一个元素时不重复执行效果 这需要用到jquery的stop方法 实例 停止当前正在运行的动画: $("#stop").click(function(){ ...
- Spring的quartz定时器同一时刻重复执行二次的问题解决
最近用Spring的quartz定时器的时候,发现到时间后,任务总是重复执行两次,在tomcat或jboss下都如此. 打印出他们的hashcode,发现是不一样的,也就是说,在web容器启动的时候, ...
随机推荐
- 无法解析的外部符号 "void __cdecl cv::imshow
解决方法: 把编译环境放到其他没有报错的项目上,编译通过.
- JS高阶---定时器相关
首先看几个问题: [主体] (1)定时器真的时定时执行的吗? 顺序验证: 测试结果: 接下来对上述代码做下修改,增加一个长时间工作的消耗,此时再来验证下定时器运行的精准度 结果如下: (2)定时器回调 ...
- 树莓派搭建SVN服务器
1.安装SVN服务器 sudo apt-get install subversion -y 2.创建仓库 mkdir /home/pi/svnRepository svnadmin create /h ...
- webpack开发指南1
怎么安装Webpack 安装node.js 首先需要安装Node.js,node自带了包管理工具npm. 安装webpack 使用npm install webpack -g,webpack全局安装到 ...
- 201871010121 王方 《面向对象程序设计(JAVA)》第七周学习总结
项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...
- jmeter引用jar包的3种方式
示例 实现对登录密码进行MD5加密 pom文件依赖 <!-- https://mvnrepository.com/artifact/commons-codec/commons-codec --& ...
- 整合SpringTask实现定时任务
一.框架介绍 SpringTask是Spring自主研发的轻量级定时任务工具,相比于Quartz更加简单方便,且不需要引入其他依赖即可使用. 二.Corn表达式 概述 Cron表达式是一个字符串,包括 ...
- (转)LoadRunner集合点设置1
集合点的意思时等到特定的用户数后再一起执行某个操作,比如一起保存,一起提交(我们通常意义上的并发数并不是指一起提交或者一起保存),一般情况下使用不到集合点,不过,订票系统或者促销类需要用到,比如说某个 ...
- TCP/IP协议族(五)
目前实际使用的网络模型是 TCP/IP 模型,它对 OSI 模型进行了简化,只包含了四层,从上到下分别是应用层.传输层.网络层和链路层(网络接口层),每一层都包含了若干协议. 协议(Protocol) ...
- 每天一道Rust-LeetCode(2019-06-11)
每天一道Rust-LeetCode(2019-06-02) Z 字形变换 坚持每天一道题,刷题学习Rust. 题目描述 全排列 II 给定一个可包含重复数字的序列,返回所有不重复的全排列. 示例: 输 ...