如何在分布式环境中创建/配置Cronjob(Laravel 5.7)
Laravel 5.7 多服务器Cronjob故障自动接管方案
针对你4台服务器需要实现Cronjob故障自动接管的需求,核心思路是利用Laravel任务调度的分布式锁机制,确保同一时间只有一台服务器执行任务,当执行任务的服务器宕机后,其他服务器会自动获取锁并接管任务。具体步骤如下:
1. 统一分布式锁存储驱动
所有服务器需要共享同一个锁存储介质,推荐用Redis(性能更优),也可以用数据库:
用Redis作为锁存储
在每台服务器的.env文件中配置:
CACHE_DRIVER=redis REDIS_HOST=你的Redis服务器地址 REDIS_PASSWORD=你的Redis密码(如果有) REDIS_PORT=6379
用数据库作为锁存储
如果没有Redis,可使用数据库:
- 运行命令生成缓存表迁移:
php artisan cache:table - 执行迁移创建
cache表:php artisan migrate - 在
.env中设置:CACHE_DRIVER=database
2. 配置任务调度的分布式锁
在app/Console/Kernel.php的schedule方法中,给需要分布式执行的任务添加onOneServer()方法:
protected function schedule(Schedule $schedule) { // 示例:每天执行一次自定义任务 $schedule->command('your:custom-task') ->daily() ->onOneServer() // 关键:确保任务仅在一台服务器执行 ->expiresIn(3600); // 设置锁有效期(秒),根据任务执行时长调整,避免任务未完成锁就过期 // 其他任务同理,按需添加onOneServer() }
onOneServer()的原理是通过共享缓存创建一个全局锁,只有获取到锁的服务器会执行任务,其他服务器会跳过。当执行任务的服务器宕机,锁过期后,其他服务器就能获取锁并执行任务。
3. 每台服务器部署相同的Cron入口
在4台服务器上都配置相同的系统Cronjob,每分钟触发Laravel调度器:
* * * * * php /你的项目根目录/artisan schedule:run >> /dev/null 2>&1
Laravel调度器会每分钟检查所有任务,判断是否需要执行,以及当前服务器是否能获取到分布式锁。
4. 关键注意事项
- 时间同步:确保4台服务器的系统时间完全同步(可配置NTP服务),否则任务执行时间会出现偏差。
- 锁有效期:根据任务实际执行时长设置
expiresIn(),如果任务执行时间超过锁有效期,会导致多台服务器重复执行任务。 - 锁存储高可用:如果用Redis,确保Redis实例是高可用的(如主从复制、集群),避免Redis单点故障导致所有任务无法执行。
- 日志排查:建议给任务添加日志输出,方便排查执行情况:
$schedule->command('your:custom-task') ->daily() ->onOneServer() ->appendOutputTo(storage_path('logs/cron_task.log'));
内容的提问来源于stack exchange,提问作者Ram Kumar
相关产品推荐
相关产品推荐

