## 案例
一个每十分钟执行一次的数据同步任务,某天夜里目标端接口响应变慢,单轮任务跑了四十分钟还没结束。下一轮的定时触发如期而至,新进程在旧进程还握着资源时启动,两边同时写同一批文件:数据出现重复与交错,下游统计对不上,更糟的是两个慢进程又各自拖出下一轮重入,机器上同时挂着四五个同名任务互相踩踏,直到早上有人发现数据全乱了。
## 根因分析
问题在设计层:任务没有重入保护,默认每一轮都能顺利在间隔内跑完,这个假设在异常时不成立。慢的目标端、突增的数据量、一次网络抖动,任何一项都能让单轮耗时超过调度间隔,而 cron 只负责按时触发,不管上一轮死活。叠加执行带来的三类危害:文件与数据的并发写坏、下游被重复推送、机器资源被多个慢任务叠加拖垮。卡死本身不致命,重入造成的脏数据才致命。
## 修复过程
修复用 flock 加锁实现单实例运行。任务命令改为:
bash flock -n /var/lock/datasync.lock /opt/scripts/datasync.sh
-n 参数的含义是拿不到锁立即退出:上一轮还在跑时,新一轮触发后直接放弃,等下个周期再来,天然杜绝叠加。配合两处加固:脚本内部对慢操作设置超时,目标端接口调用全部带超时参数,避免单轮无限拖长;任务日志记录每轮起止时间与处理量,超时或耗时异常在日志里一眼可见。上线后连续观察一周日志,重入次数与单轮耗时都有了基线。
## 复盘要点
所有定时任务上线时都该回答一个问题:单轮超过调度间隔会发生什么。答案必须是"下一轮跳过"而不是"再来一遍"。锁文件的路径与任务一一对应,日志里记录拿锁失败的跳过事件,跳过频繁说明间隔设计不合理或任务该优化了。顺云云服务器上跑多任务的机器,把锁与超时做成任务脚本的标配模板,新人复制即用,这类事故从源头堵住。