某个每小时执行一次的作业连续 9 次没有运行,日志里没有报错,锁的 key 用 TTL 查是 -1。乍看像缓存或者权限的锅,追下去往往不是。
redis-cli SET lock:hourly:sync "$(hostname):$$" NX EX 300
redis-cli TTL lock:hourly:sync
redis-cli --scan --pattern 'lock:*' | xargs -I{} redis-cli TTL {}
追下去是这么回事:拿锁用的是 SETNX 没带 EX,进程被杀后锁不会自动释放。下一次调度看到 key 存在就直接跳过,也不记录原因。
「作业锁未释放」这个问题文档写得含糊,实际行为以当前版本为准,别照旧版本的结论套。测试环境和线上的差别,往往就在版本号和那几行被忽略的配置上。
线上出问题先对时间点,跟发布、备份、任务执行的时刻排一排,能省掉一半功夫。日志级别临时调高可以,记得改回去,长期开着既占磁盘又掩盖真问题。
权限不要一口气开到最大,先加到够用再往上试,范围小才好收。
具体做法是,改成 SET key value NX EX 300 一条命令拿锁;锁的 value 用进程唯一标识 释放前比对再删;拿不到锁时打一条 info 日志 写清持有者;给锁加监控 TTL 为 -1 的 key 直接告警。
验收就看一点,手动 kill 持锁进程后 5 分钟内锁自动过期 下一次调度正常执行并留下日志。
