问题
最近在工作中经常会用到定时任务,发现当我们的脚步的执行时间(假设:130s)大于定时任务的设定时间(假设:1分钟)时,定时任务会重复开始执行,即上次的任务还没有执行完,下次的任务的又开始执行。往往执行的脚本里的资源是不允许同时两个脚本同时共享资源,即保证操作的原子性。否则会产生一连串的问题(数据重复计算等等),想想都可怕。
思路
思路很简单,就是给执行脚本或者计划去加锁。差不多有三种方式去做:
-
利用临时文件
- 在执行文件的开头先判断是否有一个 test.lock 的文件,如果有 test.lock 文件,则 exit(),如果没有的话,创建 test.lock 文件,然后执行脚本文件,执行完毕删除 test.lock
-
利用脚本加锁
- 思路和第一种方式类似,只是不是用文件判断的方式,而是给文件加锁的方式
-
利用 linux flock 锁机制
-
flock(FreeBSD lockf,CentOS下为 flock),在脚本执行前先检测能否获取某个文件锁,以防止脚本运行冲突
-
格式
flock [-sxun][-w #] fd#
flock [-sxon][-w #] file [-c] command- 选项
-s, --shared: 获得一个共享锁
-x, --exclusive: 获得一个独占锁
-u, --unlock: 移除一个锁,脚本执行完会自动丢弃锁
-n, --nonblock: 如果没有立即获得锁,直接失败而不是等待
-w, --timeout: 如果没有立即获得锁,等待指定时间
-o, --close: 在运行命令前关闭文件的描述符号。用于如果命令产生子进程时会不受锁的管控
-c, --command: 在shell中运行一个单独的命令
-h, --help 显示帮助
-V, --version: 显示版本- 锁机制
共享锁:多个进程可以使用同一把锁,常被用作读共享锁
独占锁:同时只允许一个进程使用,又称排他锁,写锁。-
这里我们需要同时只允许一个进程使用,所以使用独占锁。
修改后的定时任务如下:/1 * * * * flock -xn xxx.lock -c 'php /home/xxx.php' >> /home/xxx.log' -
完美的解决了我们的问题
-
总结来看
- 总体看来,还是用第三种方法比较好,而且也方便。