laravel 10 中任务锁通过 withoutoverlapping() 和 ononeserver() 实现,底层依赖缓存(推荐 redis),防止多进程/多服务器重复执行;前者避免单机重叠,后者保障集群唯一性,需配合使用并注意锁键隔离与超时配置。

在 Laravel 10 中,任务锁(Task Locking)主要用于防止同一任务在多个进程或服务器上重复执行,尤其在集群部署、高频调度或长时任务场景下至关重要。它不是靠数据库或外部锁服务“手动实现”,而是通过 Laravel 内置的 withoutOverlapping() 和 onOneServer() 机制自动完成,底层依赖缓存驱动(如 Redis、Memcached 或 file)来协调状态。
使用 withoutOverlapping() 防止任务重叠
该方法确保同一任务在前一次未结束前,不会被再次触发,避免资源争用或数据错乱。适用于单机或共享缓存的多实例环境。
- 默认锁过期时间为 24 小时,可通过
expiresAt()自定义:$schedule->command('process:import')->hourly()->withoutOverlapping()->expiresAt(now()->addMinutes(30)); - 若任务执行超时,旧锁会自动释放;但建议结合
runInBackground()或队列异步化,避免阻塞调度器 - 不支持跨缓存驱动的强一致性,Redis 是最推荐的后端(需配置
CACHE_DRIVER=redis)
使用 onOneServer() 确保集群唯一执行
当应用部署在多台服务器(如负载均衡集群)时,此方法保证整个集群中该任务仅由其中一台服务器执行,适合报表生成、清理类等非实时但需全局唯一的任务。
- 底层通过缓存键加锁 + 随机竞争机制实现,依赖缓存的原子操作(如 Redis 的 SETNX)
- 必须配合
withoutOverlapping()使用才更安全,例如:$schedule->command('notify:daily')->dailyAt('08:00')->onOneServer()->withoutOverlapping(); - 若当前服务器失联,锁会在过期后由其他节点接管,无单点故障风险
自定义锁键与调试技巧
默认锁键格式为 scheduler:command_name,你可显式指定以支持多环境隔离或参数化任务:
- 使用
preventOverlappingUsing()自定义键名:$schedule->command('sync:tenant', ['id' => 123])<br> ->hourly()<br> ->preventOverlappingUsing(fn () => 'sync_tenant_123'); - 检查锁是否存在:可在 Tinker 中运行
Cache::get('scheduler:cache:clear')查看锁值(通常为时间戳) - 日志中搜索
Skipping scheduled command表示因锁被跳过,是正常行为
锁机制本身不解决任务失败重试逻辑,如需容错,应结合 onFailure() 回调和队列延迟重试策略。











