























我们公司有大量的 PHP 和 Shell 脚本需要定时执行。起初使用 Linux 的 crontab 管理任务,但随着业务的增长,定时任务数量一度超过 50 个,管理成本迅速上升。
为了方便线上操作,当时在 GitHub 上找到了 lisijie/webcron 这个项目。它功能简单,能满足基本的定时任务管理需求,我们便直接投入使用。
随着时间推移,我们开始遇到以下两个关键问题:
日志数据膨胀,存储压力大
例如:
| 项目 | 月记录数 | MySQL .ibd 文件体积 |
|---|---|---|
| A 项目 | 120 万条 | 1.2 GB |
| B 项目 | 480 万条 | 8.9 GB |
如果按照此增长速度保留半年,B 项目的日志将占用约 50GB 的磁盘空间。
我们决定重构整个定时任务管理系统,重点优化三方面:
MySQL 查询开销大、影响业务,我们将日志存储迁移到 SQLite。它无需额外服务,具备完整 SQL 支持,适合做独立日志存储方案,查询性能也更可控。
观察日志内容后发现,大量输出存在重复格式,非常适合压缩。我们评估了几种压缩算法:
zstd(默认级别 / L7级别)zstd + 自训练字典gzip(Go 标准库实现)压缩对比如下:
| 压缩方案 | A 项目(120 万) | B 项目(480 万) |
|---|---|---|
MariaDB .ibd 文件 | 1.2 GB | 8.9 GB |
| SQLite 明文存储 | 856 MB | 665 MB |
| gzip(默认) | 212 MB | 405 MB |
| zstd(无字典) | 198 MB | 335 MB |
| zstd + B 项目字典 | 149 MB | 192 MB |
| zstd L7 + B 项目字典 | 139 MB | 186 MB |
| zstd + A 项目字典 | 95.1 MB | 224 MB |
注:
- 字典通过
zstd --train命令生成,使用项目历史日志训练;- 字典在不同项目中交叉使用效果不一;
- 字典需维护更新,综合考虑后未在最终方案中使用。
最终策略是:当单条日志长度 > 150 字节时启用 zstd 压缩,否则直接存储明文。读取时自动判断并解压。
为了避免单文件过大并简化清理流程,我们将日志按月分别存储,每月 1 号新建一个 SQLite 日志库文件(如 2025-08.db)。
这样带来两个好处:
.db 文件即可,维护成本极低。经过重构后,系统在实际运行中表现稳定,存储与性能均有显著改善:
日志是按行追加写入的,若采用列式压缩,需要额外拆分压缩、整合再写入逻辑,开发成本较高,不适合高频日志场景。因此我们采用了“逐行压缩”策略,开发上更轻量。
本项目思路部分参考了 V2EX 上的帖子:使用 SQLite 存日志 + zstd 压缩,但实际测试中压缩比与原贴略有差异。总体来说,该方案在中小型系统中表现优异,值得借鉴。
这次定时任务系统重构,核心目标是“日志系统轻量化、可维护、低资源占用”。通过 SQLite + zstd 压缩 + 分月归档的组合,我们在不依赖额外服务的前提下,成功将海量日志压缩到可控范围,并提升了查询体验。
如果你的系统也面临日志存储冗余、查询卡顿等问题,或许可以尝试这种“小数据库 + 压缩”的路线。
文章内容由两双筷子原创,使用 ChatGPT 进行排版优化。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。