Laravel Task Scheduling Preventing Task Overlaps
发布时间 2020年3月5日 (更新时间 2023年12月12日) • 2 分钟 读完 • 322 字Laravel Task Scheduling Preventing Task Overlaps
一个Task没有允许结束,另一个Task又起了,这固然会造成程序执行的结果不是我们想要的,为了解决这个问题我发现Laravel有提供现成的方法。
方法一:可以在代码中使用原子锁,这样即使第二个tash进程启动了,也可以阻挡住。
方法二:使用Laravel提供现成的withoutOverlapping方法,官方案例:$schedule->command('emails:send')->withoutOverlapping();
方法一中使用哪一种的锁机制,那就看自家自己的喜好了不分好坏,只分性能高低😼,个人使用redis原子锁,从2.6.12版本以后,使用锁的方式变得更为简单,如设置一个名为lock的5秒钟原子锁:SET lock 1 EX 5 NX,SET 更多参数用法
方法二我的测试结果如下:
创建测试command文件,命令:php artisan make:command Test
代码
class Test extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'test:over';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->line('Start');
\Log::info('command run time:'.date('Y-m-d H:i:s'));
sleep(90);
$this->line('End');
}
}Kernel.php代码protected $commands = [
...
...
Commands\Test::class
]
protected function schedule(Schedule $schedule)
{
...
...
$schedule->command('test:over')->everyMinute()->withoutOverlapping();
}[2020-03-09 13:00:02] production.INFO: command run time:2020-03-09 13:00:02
[2020-03-09 13:02:00] production.INFO: command run time:2020-03-09 13:02:00
[2020-03-09 13:04:02] production.INFO: command run time:2020-03-09 13:04:02
[2020-03-09 13:06:01] production.INFO: command run time:2020-03-09 13:06:01
[2020-03-09 13:08:02] production.INFO: command run time:2020-03-09 13:08:02
[2020-03-09 13:10:01] production.INFO: command run time:2020-03-09 13:10:01
[2020-03-09 13:12:02] production.INFO: command run time:2020-03-09 13:12:02
[2020-03-09 13:14:01] production.INFO: command run time:2020-03-09 13:14:01
[2020-03-09 13:16:02] production.INFO: command run time:2020-03-09 13:16:02 只要不人为干预强制启动多个schedule:run,不会有问题。
在19:32秒时强制,人为强制启动多个schedule:run进程,log如下:
[2020-03-09 13:18:01] production.INFO: command run time:2020-03-09 13:18:01
[2020-03-09 13:19:32] production.INFO: command run time:2020-03-09 13:19:32
[2020-03-09 13:22:02] production.INFO: command run time:2020-03-09 13:22:02
[2020-03-09 13:24:01] production.INFO: command run time:2020-03-09 13:24:01
[2020-03-09 13:26:02] production.INFO: command run time:2020-03-09 13:26:02
[2020-03-09 13:28:01] production.INFO: command run time:2020-03-09 13:28:01 /**
* Do not allow the event to overlap each other.
*
* @return $this
*/
public function withoutOverlapping()
{
$this->withoutOverlapping = true;
return $this->skip(function () {
return file_exists($this->mutexPath());
});
} /**
* Register a callback to further filter the schedule.
*
* @param \Closure $callback
* @return $this
*/
public function skip(Closure $callback)
{
$this->rejects[] = $callback;
return $this;
} /**
* Get the mutex path for the scheduled command.
*
* @return string
*/
protected function mutexPath()
{
return storage_path('framework'.DIRECTORY_SEPARATOR.'schedule-'.sha1($this->expression.$this->command));
}➜ ls storage/framework
cache schedule-7d2b691b1562e375e4f787cfd391d7a019e5f8cf sessions views
➜ ✗ cat storage/framework/schedule-7d2b691b1562e375e4f787cfd391d7a019e5f8cf