强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

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

关键要点

  1. 推荐使用 zstd,级别 1-5 适合大多数场景
  2. 压缩级别只影响新写入的数据
  3. compress-force 会压缩所有数据,包括已压缩的
  4. 使用 compsize 监控压缩效果
  5. SSD 使用低级别,HDD 可以用更高级别

扩展阅读