很多站点的定时任務是在上线那天随手加上的:备份資料库、生成站点地图、清理缓存、同步外部資料。加上之後很少有人再回头看,直到某天站点變慢或者磁盘寫满,才發現某個任務已经连着跑了好几天。
定时任務為什么會拖慢整站
定时任務和訪客請求共用同一台服務器的资源。CPU、内存、磁盘 IO、資料库连接數,總量都是有限的。一個任務如果比预期慢十倍,它占用的资源就會一直存在,訪客請求只能排队等。
- 導出類任務走了全表掃描,長時間占着資料库连接不放
- 备份任務反复压缩大文件,磁盘 IO 被打满
- 循环抓取外部接口却没有超时設定,一個任務挂着不結束
- 每分钟执行一次的任務,實际跑完要三分钟,實例不断堆积
- 日誌只寫不清理,几個月後把磁盘占满
自查要看的几件事
任務清單和执行频率
先把服務器上的任務列出来:crontab、systemd timer、主机面板里的計划任務,還有應用层自己的調度(部分 CMS 和插件也會寫任務)。每一項都要能说清楚三件事:做什么、多久跑一次、正常情况下跑完要多久。
执行记錄與登出狀態
只记錄“開始执行”意义不大。要能查到每次任務的開始時間、結束時間、登出碼和輸出内容。如果日誌里只有一行啟動信息,出問题时你無法判断它是卡住了,還是早就失敗登出了。
是否允许並發
有些任務本身不支持同时跑两個實例,比如全量备份、索引重建、資料對帳。如果没加鎖,上一次還没結束,下一次又啟動了,轻則輸出互相覆盖,重則把資料寫乱。
超时和重试
涉及網絡請求的任務必须设超时。重试也要有上限和間隔,否則一個外部接口挂掉之後,你的任務可能在几分钟内發出成百上千次請求,把對方和自己的带宽都拖下水。
一個可执行的排查顺序
- 列出全部任務,标注频率、预計耗时、最近一次的實际耗时
- 找出實际耗时遠大于预計耗时的任務,先翻它的日誌
- 對照任務執行时段,看服務器负载(CPU、内存、磁盘、连接數)有没有同步抬升
- 检查同一個任務是否出現了重叠执行
- 检查日誌文件、临时文件、备份文件的占用情况
- 確認失敗任務有没有告警,第二天有没有人會發現
常见的處置方式
- 把耗时長的任務挪到訪問低谷时段,並彼此错開時間
- 加互斥鎖或重入判断,保證同一任務不會重叠执行
- 给外部請求设超时和重试上限
- 日誌按天切分,並設定保留天數
- 给關键任務加告警:失敗、超时、耗时異常都要能通知到人
- 已经不需要的任務直接删掉,不要留在那里当隐患
定时任務的隐患往往不是“從来不跑”,而是“一直在跑但没跑完”。前者容易被發現,後者只會慢慢消耗资源。
小结
定时任務属于平时没人注意、出問题时影响面却很大的東西。建议每季度過一遍任務清單,確認每一項還有存在的必要、跑得完、有日誌、失敗有人知道。做到這几点,多數由定时任務引起的负载問题都能提前避開。