凌晨三点的告警不是巧合

举报
yd_222002169 发表于 2026/11/03 08:13:03 2026/11/03
【摘要】 凌晨三点的告警不是巧合 很多团队都遇到过这种场景:白天一切正常,定时任务跑得好好的,到了凌晨三点突然开始告警——任务超时、数据没更新、报表为空。值班同事第一反应是“是不是机器挂了”,登上去一看,进程还在,日志里只有一行

凌晨三点的告警不是巧合

很多团队都遇到过这种场景:白天一切正常,定时任务跑得好好的,到了凌晨三点突然开始告警——任务超时、数据没更新、报表为空。值班同事第一反应是“是不是机器挂了”,登上去一看,进程还在,日志里只有一行 context deadline exceeded 或者干脆什么都没有。

定时任务总在半夜失败,十有八九不是代码 bug,而是它运行的那段时间,整个系统环境发生了白天不存在的剧烈变化。下面几个原因,是我在真实项目里反复踩过的。

同一条流水线上,任务互相踩踏

最常见的原因:所有人都在午夜前后排定时任务。

  • 凌晨 0:00 数据归档,0:10 报表生成,0:30 全量同步,2:00 备份……
  • 这些任务共享同一个数据库或同一台 Redis,白天单个跑都很快,零点一起跑就把连接池打满。
  • 结果单任务看起来“忽快忽慢”,实际上是负载被邻居推高了几倍。

解决办法不是加大连接池,而是错峰并增加互斥。把任务从 0:00 挪到 0:05、0:17 这种随机分钟,再用 SELECT ... FOR UPDATE 或 Redis 的 SETNX 加一把分布式锁,确保同一业务键不会被并发执行。锁要带 TTL 并做续期,否则任务一卡死,锁反而成为下一次失败的根因。

数据库的“凌晨状态”和你想象的不一样

白天数据库有热缓存、有稳定连接,凌晨经过一段空闲后,很多事情变了:

  • 连接池里的空闲连接被服务端 wait_timeout 回收,任务拿到的第一条连接直接报 MySQL server has gone away。
  • 白天被缓存挡住的慢查询,凌晨冷缓存下第一次执行直接超时。
  • 如果数据库有夜间备份或主从延迟,SELECT 读到的可能是尚未同步完成的数据。

实操上:连接池配置 testOnBorrow 或定期 validationQuery;任务里把长事务拆小,避免一个事务持锁十几分钟;对关键读取显式指定主库,别让半夜的查询悄悄落到延迟的从库上。还有一点容易被忽略——定时任务里的 SQL 也要加超时,否则一个慢查询会把整个调度线程卡死,后面排队的任务全部顺延。

任务自己把内存和句柄吃光了

不少半夜失败的任务,其实是“一个晚上跑了很多次”造成的。典型表现:

  • 任务每 5 分钟触发一次,上一次还没结束下一次就来了,进程越堆越多。
  • 有的实现用 setInterval 而不是 setTimeout 递归,间隔固定、执行不保证,短时间爆发后内存被打爆。
  • 脚本里打开的文件、数据库游标、HTTP 连接没关闭,跑几千轮后 ulimit -n 触顶,报 Too many open files。

凌晨触发频率低,问题不明显;一旦某个日终批量把调度间隔挤密,堆积就出现了。修复方式:给任务加单实例占位锁,上一轮没结束直接跳过并打日志;用 try/finally 或 with 结构保证资源释放;调度层记录“上次开始/结束时间”和连续跳过次数,超过阈值告警,而不是默默堆积到天亮。

时间本身会骗你:时区、夏令时与时钟漂移

如果你的凌晨任务在 2:00~3:00 之间,请立刻检查时区。夏令时切换会让这个小时直接消失或重复一次,很多调度框架在这天要么跳过任务,要么同一个任务跑两遍。服务器用 UTC、业务按本地时间、cron 又按机器时区写,三者叠加就是灾难。

实操建议:

  • cron 表达式统一按 UTC 写,业务需要本地时间就在代码里换算。
  • 任务里记录实际执行时间戳,而不是只看 HH:mm。
  • 对有状态的调度(如 Quartz)确认是否开启了 misfire 补跑,补跑没有幂等保护就会重复写数据。

把“半夜”当成一等公民来排查

凌晨失败难查,是因为没人看着它跑 lag。改掉这个习惯:在任务里加结构化日志——开始/结束时间、耗时、堆栈、读了哪个库连了哪台机、当前内存和句柄数;失败时把日志和当时的系统指标一起留存,而不是事后去猜。

再加一条:拿最闲的那台预发环境,把 cron 在白天手动跑一遍,效果完全不同——因为异常往往靠“抢资源”触发,而白天本来就没什么可抢的。既然问题在夜里爆发,就让它在夜里被复现和观察,这才是排查定时任务最务实的方式。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。