Btrfs 文件系统运维完全教程 / 第 6 章:数据压缩
第 6 章:数据压缩
6.1 Btrfs 压缩概述
Btrfs 支持透明压缩(Transparent Compression),数据在写入磁盘前自动压缩,读取时自动解压,对应用程序完全透明。
压缩的工作原理
应用程序写入数据
│
▼
Btrfs 文件系统
│
▼
压缩引擎(zstd/lzo/zlib)
│
▼
压缩后写入磁盘
磁盘读取数据
│
▼
Btrfs 文件系统
│
▼
解压引擎
│
▼
返回原始数据给应用程序
支持的压缩算法
| 算法 | 说明 | 内核要求 |
|---|---|---|
| zstd | Zstandard,Facebook 开发,压缩率和速度平衡 | 4.14+(级别支持 5.15+) |
| lzo | Lempel-Ziv-Oberhumer,极快但压缩率较低 | 所有版本 |
| zlib | 与 gzip 相同算法,压缩率高但较慢 | 所有版本 |
| no | 不压缩 | — |
6.2 压缩算法详解
6.2.1 zstd(推荐)
zstd(Zstandard)是目前 Btrfs 推荐的压缩算法:
| 压缩级别 | 压缩速度 | 解压速度 | 压缩率 | 适用场景 |
|---|---|---|---|---|
| 1 | 极快 | 极快 | 中等 | 实时压缩,低延迟 |
| 3(默认) | 快 | 极快 | 较好 | 通用推荐 |
| 5 | 中等 | 快 | 好 | 存储优先 |
| 9 | 慢 | 快 | 很好 | 归档数据 |
| 15 | 很慢 | 快 | 极好 | 长期存储 |
| 19 | 极慢 | 中等 | 最佳 | 极限压缩 |
# 使用 zstd 默认级别(3)
mount -o compress=zstd /dev/sdb1 /mnt
# 指定压缩级别
mount -o compress=zstd:1 /dev/sdb1 /mnt # 快速
mount -o compress=zstd:3 /dev/sdb1 /mnt # 默认
mount -o compress=zstd:9 /dev/sdb1 /mnt # 高压缩
mount -o compress=zstd:15 /dev/sdb1 /mnt # 归档
# 查看 zstd 压缩比
btrfs filesystem df /mnt
6.2.2 lzo
LZO 速度极快,但压缩率低于 zstd:
| 特性 | 说明 |
|---|---|
| 压缩速度 | 极快(比 zstd 快 2-3 倍) |
| 解压速度 | 极快 |
| 压缩率 | 较低(约 2:1) |
| CPU 占用 | 极低 |
| 适用场景 | 低延迟要求、实时压缩 |
# 使用 lzo 压缩
mount -o compress=lzo /dev/sdb1 /mnt
6.2.3 zlib
zlib 与 gzip 使用相同算法,压缩率最高但最慢:
| 特性 | 说明 |
|---|---|
| 压缩速度 | 慢 |
| 解压速度 | 中等 |
| 压缩率 | 高(约 3:1) |
| CPU 占用 | 高 |
| 适用场景 | 冷数据、归档存储 |
# 使用 zlib 压缩
mount -o compress=zlib /dev/sdb1 /mnt
6.2.4 算法对比
| 指标 | zstd:3 | lzo | zlib |
|---|---|---|---|
| 压缩速度 | ★★★★ | ★★★★★ | ★★ |
| 解压速度 | ★★★★★ | ★★★★★ | ★★★ |
| 压缩率 | ★★★★ | ★★★ | ★★★★★ |
| CPU 开销 | 中 | 低 | 高 |
| 内存开销 | 中 | 低 | 中 |
| 推荐场景 | 通用 | 实时/低延迟 | 归档 |
6.3 压缩配置
6.3.1 挂载选项
# 启用压缩(默认算法和级别)
mount -o compress /dev/sdb1 /mnt
# 指定算法和级别
mount -o compress=zstd:3 /dev/sdb1 /mnt
# 强制压缩所有数据
# 默认情况下 Btrfs 会跳过不可压缩的数据(如已压缩的视频)
# compress-force 会尝试压缩所有数据
mount -o compress-force=zstd:3 /dev/sdb1 /mnt
compress vs compress-force:
| 行为 | compress | compress-force |
|---|---|---|
| 可压缩数据 | 压缩 | 压缩 |
| 已压缩数据(视频等) | 跳过 | 仍然尝试压缩 |
| 性能影响 | 较小 | 可能较大 |
| 推荐场景 | 通用 | 混合数据类型 |
6.3.2 压缩级别与内核版本
# 查看内核是否支持压缩级别
uname -r
# 5.15+ 支持 zstd 级别
# 5.19+ 支持 zstd 所有级别 (1-15)
# 6.2+ 支持 zstd 最高级别 (1-19)
# 验证压缩设置
mount | grep /mnt
# /dev/sdb1 on /mnt type btrfs (rw,relatime,compress=zstd:3)
6.3.3 按文件扩展名选择性压缩
Btrfs 会根据文件内容自动判断是否压缩,但也可以通过文件属性控制:
# 禁用某个文件的压缩
chattr +m /path/to/video.mp4
# 强制压缩某个文件
chattr +c /path/to/textfile.txt
# 查看文件属性
lsattr /path/to/file
📝 注意:
chattr +m禁用压缩,chattr +c启用压缩。但 Btrfs 的实际行为取决于挂载选项和内核版本。
6.3.4 永久配置
# /etc/fstab 中配置压缩
UUID=xxx /data btrfs defaults,compress=zstd:3,noatime,space_cache=v2 0 0
# 对于根分区
UUID=xxx / btrfs subvol=/@,defaults,compress=zstd:1,ssd,discard=async 0 0
6.4 在线切换压缩
6.4.1 重新挂载切换
# 当前挂载(无压缩)
mount | grep /mnt
# /dev/sdb1 on /mnt type btrfs (rw,relatime)
# 在线启用压缩
sudo mount -o remount,compress=zstd:3 /mnt
# 验证
mount | grep /mnt
# /dev/sdb1 on /mnt type btrfs (rw,relatime,compress=zstd:3)
# 切换压缩算法
sudo mount -o remount,compress=lzo /mnt
# 禁用压缩
sudo mount -o remount,compress=no /mnt
📝 注意: 重新挂载只影响新写入的数据,已写入的数据保持原有压缩状态。要对已有数据重新压缩,需要使用 balance 操作。
6.4.2 对已有数据重新压缩
# 方法 1:使用 balance 重新压缩(推荐)
sudo btrfs balance start -dcompress -mcompress /mnt
# 指定压缩算法
sudo btrfs balance start -dcompress=zstd:3 -m /mnt
# 方法 2:复制文件触发重新压缩
sudo cp --reflink=never /mnt/largefile /mnt/largefile.tmp
sudo mv /mnt/largefile.tmp /mnt/largefile
6.5 监控压缩效果
6.5.1 查看压缩比
# 查看空间使用情况
sudo btrfs filesystem df /mnt
# 查看详细使用(包括压缩节省的空间)
sudo btrfs filesystem usage /mnt
# 查看特定目录的压缩效果
sudo compsize /mnt/data
# Processed 1000 files, 200 regular extents (200 refs), 800 inline.
# Type Perc Disk Usage Uncompressed Referenced
# TOTAL 45% 10.00GiB 22.00GiB 22.50GiB
# none 100% 2.00GiB 2.00GiB 2.10GiB
# zstd 37% 8.00GiB 20.00GiB 20.40GiB
compsize 工具详解:
# 安装 compsize
sudo apt install compsize # Debian/Ubuntu
sudo dnf install compsize # Fedora
sudo pacman -S compsize # Arch
# 查看压缩统计
sudo compsize /mnt
# Type Perc Disk Usage Uncompressed Referenced
# TOTAL 45% 10.00GiB 22.00GiB 22.50GiB
# none 100% 2.00GiB 2.00GiB 2.10GiB ← 未压缩数据
# zstd 37% 8.00GiB 20.00GiB 20.40GiB ← zstd 压缩数据
| 字段 | 说明 |
|---|---|
| Type | 压缩算法类型 |
| Perc | 压缩率百分比(越低越好) |
| Disk Usage | 磁盘实际使用空间 |
| Uncompressed | 压缩前大小 |
| Referenced | 引用的逻辑大小 |
6.5.2 单文件压缩信息
# 查看文件的物理布局
sudo filefrag -v /mnt/largefile
# 使用 btrfs 查看 extent 信息
sudo btrfs inspect-internal file-extent-map /mnt/largefile
# 或
sudo btrfs inspect-internal logical-resolve <logical_addr> /mnt
6.6 压缩性能调优
6.6.1 压缩级别选择指南
| 数据类型 | 推荐级别 | 原因 |
|---|---|---|
| 日志文件 | zstd:1 或 lzo | 低延迟写入 |
| 用户文档 | zstd:3 | 好的压缩率 |
| 源代码 | zstd:3 | 文本数据压缩效果好 |
| 虚拟机磁盘 | compress-force=zstd:3 | 混合数据 |
| 数据库 | 不压缩 | 避免额外开销 |
| 视频/图片 | 不压缩 | 已压缩数据 |
| 备份归档 | zstd:9-15 | 最大压缩率 |
6.6.2 SSD vs HDD 压缩策略
SSD:
# SSD 上使用较低压缩级别(减少 CPU 开销,SSD 速度已够快)
mount -o compress=zstd:1,ssd,discard=async /dev/sdb1 /mnt
HDD:
# HDD 上使用较高压缩级别(压缩可减少磁盘 I/O,弥补 CPU 开销)
mount -o compress=zstd:5 /dev/sdb1 /mnt
6.6.3 压缩对性能的影响
| 场景 | 压缩影响 |
|---|---|
| 顺序读 | 略有增加延迟(解压),但更少磁盘 I/O |
| 顺序写 | 增加 CPU 使用,但减少磁盘写入量 |
| 随机读 | 压缩可能导致读放大 |
| 随机写 | COW + 压缩可能加剧碎片化 |
| 大文件 | 压缩收益明显 |
| 小文件 | 压缩开销可能超过收益 |
6.6.4 内存和 CPU 开销
# 查看压缩使用的内存
cat /proc/fs/btrfs/features
# 或
cat /sys/fs/btrfs/<uuid>/compression_stats
# 监控 CPU 使用
top -p $(pgrep btrfs)
6.7 业务场景实战
6.7.1 Web 服务器日志压缩
# /var/log 日志目录
mount -o compress=zstd:1,noatime /dev/sdb1 /var/log
# 日志写入频繁,使用最低压缩级别
6.7.2 虚拟机磁盘压缩
# 虚拟机镜像存储
mount -o compress-force=zstd:5 /dev/sdb1 /vms
# force 是因为虚拟机磁盘内可能有压缩数据
6.7.3 NAS 文件服务器
# NAS 共享存储
mount -o compress=zstd:3,noatime /dev/sdb1 /nas
# 通用压缩,平衡速度和压缩率
6.7.4 归档存储
# 冷数据归档
mount -o compress=zstd:15 /dev/sdb1 /archive
# 高压缩级别,存储优先
6.8 本章小结
| 操作 | 命令 |
|---|---|
| 启用压缩 | mount -o compress=zstd:3 /dev/sdX /mnt |
| 在线切换 | mount -o remount,compress=lzo /mnt |
| 强制压缩 | mount -o compress-force=zstd /dev/sdX /mnt |
| 禁用压缩 | mount -o remount,compress=no /mnt |
| 查看压缩比 | compsize /mnt |
| 重新压缩 | btrfs balance start -dcompress /mnt |
关键要点:
- 推荐使用
zstd,级别 1-5 适合大多数场景 - 压缩级别只影响新写入的数据
compress-force会压缩所有数据,包括已压缩的- 使用
compsize监控压缩效果 - SSD 使用低级别,HDD 可以用更高级别