4、日志文件管理:文件滚动策略、命名规范与压缩归档
日志文件管理,说白了就是解决一个核心问题:日志不能无限增长。
我见过不少团队,日志文件写到几十个GB才想起来处理。结果呢?磁盘爆了,系统挂了,排查问题连日志都打不开。嗯,这种坑我踩过不止一次。
今天咱们就聊聊日志文件管理的三个关键点:滚动策略、命名规范、压缩归档。这三件事做好了,你的日志系统才能稳定跑上几年不出幺蛾子。
4.1 文件滚动策略
滚动策略,就是决定「什么时候切一个新文件」。常见的策略有两种:按大小滚动、按时间滚动。也可以两者结合。
4.1.1 按大小滚动
这个最直观。设定一个阈值,比如 100MB。日志文件一超过这个大小,立马切一个新文件出来。
我个人习惯用 256MB 或 512MB。为什么?太小了文件太多,管理麻烦;太大了单个文件打开慢,检索也慢。
maxFileSize:单个日志文件的最大大小maxBackupIndex:保留的备份文件数量
举个例子,Logback 的配置是这样的:
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/var/log/trade/trade.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>/var/log/trade/trade.%i.log.zip</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>10</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>256MB</maxFileSize>
</triggeringPolicy>
</appender>
这里有个坑:maxBackupIndex 别设太大。我曾经见过有人设了 100,结果磁盘上堆了几十个 GB 的旧日志。你想想看,滚动策略本来是为了控制磁盘,结果反而把磁盘撑爆了,这不是本末倒置吗?
4.1.2 按时间滚动
按时间滚动,就是每隔一段时间切一个新文件。常见的有:
| 滚动周期 | 适用场景 | 文件名示例 |
|---|---|---|
| 每小时 | 高频交易、实时监控 | trade.2025-01-15-14.log |
| 每天 | 大多数业务系统 | trade.2025-01-15.log |
| 每周 | 低频系统、归档日志 | trade.2025-01-13.log |
我个人建议:量化系统用每小时滚动。为什么?因为交易时段内日志量巨大,一天一个文件可能就几个GB,查问题的时候打开都费劲。按小时切,每个文件几百MB,刚好。
Logback 的按时间滚动配置:
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/var/log/trade/trade.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>/var/log/trade/trade.%d{yyyy-MM-dd-HH}.log.gz</fileNamePattern>
<maxHistory>168</maxHistory> <!-- 保留7天 -->
</rollingPolicy>
</appender>
maxHistory 控制的是保留天数,不是文件个数。
4.1.3 混合策略
实际生产中,我推荐按大小 + 按时间混合滚动。比如:每小时切一次,但如果某个小时内日志量特别大,超过 512MB 也提前切。
这样做的好处很明显:既控制了单个文件的大小,又保证了时间维度的可追溯性。
Logback 支持这种策略,用 SizeAndTimeBasedRollingPolicy:
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>/var/log/trade/trade.%d{yyyy-MM-dd-HH}.%i.log.gz</fileNamePattern>
<maxFileSize>512MB</maxFileSize>
<maxHistory>168</maxHistory>
<totalSizeCap>50GB</totalSizeCap>
</rollingPolicy>
注意那个 %i,它代表同一小时内的文件序号。比如 14 点产生了 3 个文件,就是 trade.2025-01-15-14.0.log.gz、trade.2025-01-15-14.1.log.gz、trade.2025-01-15-14.2.log.gz。
4.2 日志文件命名规范
命名规范这事,看着简单,但做不好真能坑死人。我接手过一个系统,日志文件名长这样:log1.txt、log2.txt…… 你猜哪个是今天的?哪个是昨天的?完全靠猜。
好的命名规范,应该让人一眼就能看出:这是什么日志、什么时候产生的、是第几个文件。
我推荐的标准格式:
{应用名}.{日志类型}.{日期}.{序号}.{后缀}
举个例子:
trade-system.error.2025-01-15.0.logtrade-system.access.2025-01-15.1.log.gzrisk-engine.order.2025-01-15-14.0.log
- 应用名在前:方便按应用归类
- 日志类型明确:error、access、trade、order 等
- 日期格式统一:推荐 yyyy-MM-dd 或 yyyy-MM-dd-HH
- 序号从0开始:同一时间段内多个文件时区分
- 后缀表明状态:.log 是当前写入,.log.gz 是已压缩
这里有个小技巧:当前正在写的文件不要带日期。比如用 trade.log 作为当前文件,滚动后才重命名为带日期的文件。这样你在 tail -f 的时候就不用猜文件名了。
4.3 日志文件压缩与归档
日志文件不压缩,磁盘很快就扛不住了。尤其是量化系统,一天几个GB的日志很常见。
4.3.1 压缩策略
我建议滚动的同时进行压缩。也就是文件一切换,立刻压缩成 gz 格式。这样做的好处:
- 节省磁盘空间,压缩比通常在 5:1 到 10:1
- 减少 IO 压力,小文件读写更快
- 方便传输和归档
Logback 原生支持 gzip 压缩,只要在 fileNamePattern 里加上 .gz 后缀就行。上面给的例子已经包含了。
- gzip:压缩率高,CPU 消耗适中,最常用
- zstd:压缩更快,适合高频场景
- lz4:极速压缩,但压缩率低一些
我个人习惯用 gzip,兼容性最好。如果你对压缩速度有要求,可以试试 zstd。
4.3.2 归档策略
压缩后的日志,不能一直留在生产服务器上。你需要定期归档到冷存储或对象存储。
归档的典型流程:
- 日志文件滚动并压缩
- 本地保留最近 N 天(比如 7 天)
- 超过 N 天的日志,自动上传到 S3、OSS 或 HDFS
- 上传成功后,删除本地文件
我见过一个不错的做法:用 cron + rsync 或者 fluentd 做归档。简单可靠,不需要引入太重的东西。
# 每天凌晨3点归档前一天的日志
0 3 * * * /usr/local/bin/archive_logs.sh
# archive_logs.sh 内容示例
#!/bin/bash
LOG_DIR="/var/log/trade"
ARCHIVE_DIR="/mnt/archive/trade"
DATE=$(date -d "yesterday" +%Y-%m-%d)
# 移动并压缩
find $LOG_DIR -name "*.log" -mtime +1 -exec gzip {} \;
find $LOG_DIR -name "*.log.gz" -mtime +1 -exec mv {} $ARCHIVE_DIR/ \;
# 清理本地超过7天的文件
find $LOG_DIR -name "*.log.gz" -mtime +7 -delete
if [ -f already_uploaded.txt ] 的判断就能避免。
4.4 知识体系总览
下面这张图,把日志文件管理的核心逻辑串起来了。你可以看到,从日志产生到最终归档,每一步都有对应的策略和规范。
说白了,日志文件管理就是一套「产生 → 滚动 → 命名 → 压缩 → 归档」的流水线。每个环节都做好,你的日志系统才能稳定、高效、可追溯。
我个人经验是:先把滚动策略和命名规范定死,这两个是基础。压缩和归档可以后续优化,但基础打不好,后面全是坑。