日志归档用 gzip 还是 zstd?174MB access.log 实测 8 档压缩

举报
yd_241723161 发表于 2026/11/08 01:37:34 2026/11/08
【摘要】 用一份 174MB access.log 实测 gzip 与 zstd 共 8 档压缩,对比体积、压缩速度和解压速度,最后给出归档选型建议。

服务器上的日志一直是 logrotate 默认的 gzip 在压。最近归档目录越来越大,想换 zstd,但不想凭感觉换,于是拿一份 174MB 的访问日志把两边常用的几个级别都跑了一遍。

测试环境

  • 系统:Debian GNU/Linux 13 (trixie),2 核,内存约 7.9G,没有 root
  • 版本:gzip 1.13,zstd v1.5.7
  • 样本:脚本生成的 Nginx combined 格式日志,1500000 行,182234902 字节(ls 显示 174M)

样本长这样,IP 用的是文档保留段:

$ head -2 access.log
203.0.113.243 - - [01/Nov/2026:00:00:00 +0800] "GET /api/v1/login HTTP/1.1" 200 3364 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/130.0"
203.0.113.138 - - [01/Nov/2026:00:00:00 +0800] "GET /api/v1/items HTTP/1.1" 200 4001 "-" "curl/8.5.0"

先说清楚一点:这是生成出来的日志,字段重复度和真实业务日志不完全一样,压缩比的绝对值只能参考,几档之间的相对关系才是重点。

测试脚本

一开始我想用 /usr/bin/time -v 顺便看内存峰值,结果脚本直接退出码 127,输出文件全是空的。这台机器是精简系统,压根没装 time 这个包,又没 sudo 装不上。干脆改用 bash 自带的 time 关键字,只记墙钟时间:

#!/usr/bin/env bash
# 用法: ./bench.sh access.log
f=$1; TIMEFORMAT=%R
for c in "gzip -1" "gzip -6" "gzip -9" "zstd -1" "zstd -3" "zstd -9" "zstd -3 -T0"; do
  t=$( { time $c -c "$f" > out.tmp 2>/dev/null; } 2>&1 )
  printf '%-12s %7ss %10s bytes\n' "$c" "$t" "$(stat -c %s out.tmp)"
done
rm -f out.tmp

TIMEFORMAT=%R 让 time 只输出一个秒数,方便塞进变量。zstd -19 没放进循环,原因后面说。

$ ./bench.sh access.log
gzip -1        1.059s   21187316 bytes
gzip -6        1.790s   15143711 bytes
gzip -9        5.557s   13715907 bytes
zstd -1        0.285s   19139328 bytes
zstd -3        0.391s   18935241 bytes
zstd -9        2.369s   13238587 bytes
zstd -3 -T0    0.260s   18935241 bytes

这组数字我前后跑了两轮,第二轮 zstd -3 是 0.391s,第一轮是 0.525s,波动不小;gzip 两轮几乎一样。小文件计时本来就容易抖,看量级就行。

压缩:体积和速度

几个让我意外的地方:

  1. zstd -3(默认级别)比 gzip -6 快 4.6 倍左右,但体积大 25%。如果只看默认值对默认值,zstd 在日志上并没有更省空间。
  2. 真正能比 gzip -6 小的是 zstd -9:13238587 对 15143711 字节,小了 12.6%,压缩耗时 2.369s 对 1.790s,只慢三成。
  3. gzip -9 很不划算:比 -6 多花 3 倍时间,只小了 9.4%,而且还比 zstd -9 大。
  4. -T0 开多线程后耗时从 0.391s 降到 0.260s,输出字节数完全一样。2 核机器上能有这个提升已经可以了。

zstd -19 跑了 217 秒

-19 我单独跑的,原以为几十秒就完事,结果等了 217.451 秒,得到 11791863 字节。比 -9 再小 11%,但耗时是 -9 的九十多倍。每天切一次日志的话,3 分多钟占着一个核还能忍;日志量再大一点就不现实了。所以它没进循环,不然每次跑脚本都得干等。

解压:差距最大的一项

归档的日志总有要翻出来查的时候,zcat | grep 的速度其实比压缩速度更影响体验。

$ TIMEFORMAT=%R
$ time (gzip -dc out.gzip-9 > /dev/null)
0.618
$ time (zstd -dc out.zstd-9 > /dev/null)
0.109

另外两个:gzip -6 解压 0.623s,zstd -3 是 0.129s,zstd -19 是 0.140s。gzip 不管压的时候用几级,解压都在 0.62s 上下;zstd 都在 0.1 秒出头,-19 压得那么狠,解压也没变慢。算下来 zstd 解压快 5 倍左右。

验证:压完能原样还原

速度再快,解不回原文件也没用。拿最狠的 -19 做一次往返校验:

$ md5sum access.log
d557650926e88a32bd4373fbea8dc313  access.log
$ zstd -dc out.zstd-19 | md5sum
d557650926e88a32bd4373fbea8dc313  -
$ gzip -t out.gzip-6 && echo ok
ok

两边 md5 一致。gzip -t 和 zstd -t 都能只校验不落盘,放在归档脚本最后一步挺合适。

怎么选

  • 只想要更快、不在乎体积:zstd -3 加 -T0,比 gzip -6 快好几倍,体积大一些。
  • 想同时省空间和时间:zstd -9,比 gzip -6 小 12% 左右,压缩略慢,解压快 5 倍。我自己的归档会换成这个。
  • zstd -19 只适合一次性的冷备份,日常轮转别用。
  • gzip -9 没有使用场景,要么 -6,要么直接换 zstd。
  • 换之前确认下游工具认 .zst:zstdcat、zstdgrep 都有,但有些老脚本写死了 zcat,这步别省。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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