Hyperf防止定时任务重复执行依赖单机级singleton锁(基于文件锁)与集群级onOneServer锁(基于Redis分布式锁),二者需配合使用;仅启用@Crontab注解而未配置对应锁机制,在多进程或K8s多副本下必然导致重复执行。

Hyperf 防止定时任务重复执行,核心靠两级锁机制:单机层防并发 + 分布式层防集群重复。光开 @Crontab 注解不配锁,多进程或 K8s 多副本下必然出问题。
单机级锁(singleton)
解决同一台机器上多个 worker 进程同时触发同一任务的问题。配置 singleton = true 后,Hyperf 会在本地用文件锁(默认 /tmp/hyperf-crontab-{task_name}.lock)做互斥:
- 每个任务启动前尝试原子创建锁文件(
os.open(..., O_CREAT | O_EXCL)),成功才执行 - 执行结束或异常退出时自动清理锁文件(由框架内部
finally保障) - 不依赖外部服务,轻量、可靠,但仅限单机有效
集群级锁(onOneServer)
解决多台服务器(如 K8s 多 Pod)同时执行同一任务的问题。必须启用 Redis,并配置 onOneServer = true:
- 底层调用 Redis 的
SET key value NX PX {mutexExpires}实现分布式锁 - 默认过期时间 60 秒(可调
mutexExpires),避免死锁 - 锁 key 自动生成,格式为
crontab:lock:{task_name},所有节点竞争同一 key - 获取失败直接跳过本次调度,不阻塞、不重试
Hyperf 锁配置关键项
在任务类中通过注解或配置文件设置:
-
singleton:布尔值,控制单机是否只允许一个实例运行 -
onOneServer:布尔值,开启后启用 Redis 分布式锁 -
mutexPool:指定使用的 Redis 连接池名(需提前配置好) -
mutexExpires:锁自动过期秒数,建议设为任务最大执行时间的 1.5 倍
避坑提醒
常见失效场景和应对方式:
- K8s 环境下未配置 Redis 或连接池不可用 → 锁退化为无锁,务必检查
redis.default配置和网络连通性 - 任务执行超时但锁已过期 → 其他节点可能介入,应监控实际耗时并调大
mutexExpires - 使用
@Crontab却没开onOneServer→ 在集群中仍会重复执行,不是“开了注解就安全” - 秒级任务搭配
crontab-dispatcher→ 易内存泄漏,推荐改用beforeStart中的协程定时器 + 手动加锁


















