跳到主要内容
弗美科技
技术分享

定时任务跑了两遍,那个凌晨的对账单

每天凌晨 2 点跑的对账脚本,某天生成了两份汇总,客户财务早上对着两张表愣了半天。原因不是脚本写错,是 crontab 里同一条被贴了两遍,中间隔了 7 行没看见。后来加了文件锁 flock、每次运行写 run_id、日志落一张表,还把 crontab 收进 Git。

2017年10月13日定时任务踩坑记录对账

凌晨 2 点的对账脚本跑了小半年没出事,10 月 13 号早上客户财务发来截图:同一天的汇总有两份,金额差了一笔。

1. 第一反应是脚本有 bug

查了半小时脚本,幂等逻辑看着没问题,按日期加门店号做了唯一键。翻执行日志才发现,2:00 和 2:01 各有一条完整记录,两次都跑完了。

2. crontab 里同一行贴了两遍

登服务器 crontab -l,一屏 30 多行,第 8 行和第 15 行一模一样。之前加一个临时补数任务时复制粘贴,补完忘了删,两次间隔刚好 1 分钟。第二遍跑的时候第一批数据已经写库,唯一键挡住了明细,但汇总表是按「本次运行」插的,于是多了一行。

3. 为什么唯一键没拦住汇总

明细表有 UNIQUE(date, store_id),汇总表没有,它存的是每次运行的时间、条数、合计。设计的时候默认「一天只会跑一次」,这个默认没写进任何约束里。补上了 UNIQUE(run_date)。

4. 加文件锁

脚本开头加一行 flock:拿不到 /var/lock/daily_recon.lock 就直接退出并记一条日志。这样就算将来又贴重复,第二个进程也进不来。锁文件放 /var/lock,重启会清,不会锁死。

5. 每次运行先拿 run_id

现在脚本第一件事是往 run_log 表插一条,拿到自增 id,后面所有写入都带这个 run_id。出问题时按 id 一查,这次跑了哪些步骤、写到哪张表、几点开始几点结束,一目了然。那次如果有这东西,不用猜。

6. crontab 收进 Git

以前服务器上的 crontab 是谁想改谁 ssh 上去 crontab -e。现在仓库里放一份 crontab 文件,改完走一遍部署脚本下发,服务器上的那份只读。diff 一眼能看出多了哪行。

那两张表

客户财务后来把重复的汇总删了一行,没造成别的影响。我们把 10 月 13 号记进了内部的一个小本子,标题就四个字:别信默认。

商务咨询 · 免费初步沟通

需要针对你的场景给个建议?

把业务背景和当前系统情况告诉我们,我们会给出可执行的思路。

在线留言

周一至周五 9:00–18:00 · 工作日 9:00–18:00 响应,留言会在一个工作日内回复。

商务微信
商务微信二维码

扫一扫,加商务微信咨询服务与方案报价

或填写需求表单