重入与并发保护是什么
定时任务的重入指上一次实例尚未结束,下一次触发又启动了新实例,两份实例并发操作同一资源,产生重复写入、状态冲突甚至数据损坏。保护手段分四类:进程级独占锁(flock、pid 文件加存活检测)、调度器级抑制(同一服务单元不并发、CronJob 的禁止并发策略)、分布式租约锁(Redis 或数据库唯一键,带过期时间)、以及把任务本身设计成幂等,即使真的并发也不产生错误结果。最后一道防线是可观测性:跳过与拒绝必须被记录。
基本信息
| 常用手段 | flock、pid 文件加 kill -0 检测、systemd 单元抑制、Redis SET NX PX 租约锁、数据库唯一键 |
|---|---|
| 并发策略 | 跳过本次、终止上一次、排队等待(三选一需明确) |
| 关键要求 | 锁必须有过期或清理机制,异常路径也要释放 |
| 观测指标 | 跳过次数、并发被拒次数、锁等待时长 |
典型使用场景
- 每 5 分钟执行一次的同步任务偶尔超过 5 分钟
- 备份任务执行期间禁止再次启动
- 多实例部署的调度器需要全局互斥
- 进程被重启时可能已有旧实例仍在运行
- 同一资源不能被两个任务同时处理
锁与并发策略写法
锁与并发策略写法
# flock:非阻塞独占,取不到锁直接退出,适合定时任务
exec 9>/var/lock/backup.lock
flock -n 9 || { echo "上一次仍在运行,跳过"; exit 0; }
/opt/bin/backup.sh
# Redis 风格租约锁:设置过期时间,避免持锁者宕机后锁永久占用
# SET lock:backup <token> NX PX 600000
# Kubernetes CronJob 禁止并发(上一次未完成时跳过本次)
# concurrencyPolicy: Forbid互斥手段对比
| 手段 | 作用范围 | 注意点 |
|---|---|---|
| flock | 单机 | 进程退出即释放,最可靠 |
| pid 文件 | 单机 | 进程号被复用可能误判,需配合进程名校验 |
| 调度器抑制 | 单机或集群 | 依赖调度器行为,跨调度器无效 |
| Redis 租约锁 | 多机 | 需处理租约到期、续期与释放 |
| 数据库唯一键 | 多机 | 可顺带记录执行历史与审计 |
取不到锁通常应记为「跳过」而不是失败,否则监控会出现大量假告警。但跳过次数必须被统计:长期频繁跳过说明周期设置与任务实际耗时已经不匹配。
pid 文件锁在主机重启或进程被强杀后会残留。判断存活时要同时校验进程是否存在以及它是否就是同一个任务,否则会永久阻塞后续执行。