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

Bcachefs 完全指南 / 第 8 章:压缩策略

第 8 章:压缩策略

用 CPU 换空间,还是用空间换速度?


8.1 压缩概述

8.1.1 为什么需要压缩

压缩的价值:
┌─────────────────────────────────────────────┐
│ 1. 节省存储成本                              │
│    SSD 1TB ≈ ¥600                           │
│    压缩比 3:1 → 等效 3TB → 节省 ¥1200       │
├─────────────────────────────────────────────┤
│ 2. 提高 I/O 吞吐                            │
│    压缩 100MB → 读取 33MB → 传输更快         │
│    变相提高磁盘带宽                          │
├─────────────────────────────────────────────┤
│ 3. 减少写放大 (SSD)                          │
│    压缩后写入更少数据 → 延长 SSD 寿命         │
└─────────────────────────────────────────────┘

8.1.2 Bcachefs 压缩特性

特性说明
透明压缩应用程序无需感知
按块压缩独立压缩每个数据块
算法可选lz4 / zstd / gzip
级别可调每个算法支持多个压缩级别
在线切换可在运行时切换算法
不可压缩检测自动跳过不可压缩数据

8.2 压缩算法详解

8.2.1 LZ4

# 创建使用 LZ4 的文件系统
sudo bcachefs format /dev/sdb --compression=lz4

# LZ4 特点:
# - 极快的压缩/解压速度
# - 中等压缩比
# - 最低 CPU 开销

LZ4 技术指标:

指标
压缩速度~780 MB/s
解压速度~4000 MB/s
压缩比~2.1:1 (文本)
CPU 开销极低
内存使用64 KB

适用场景:

  • ✅ 实时压缩需求
  • ✅ CPU 资源有限
  • ✅ 延迟敏感型应用
  • ✅ 已部分压缩的数据(视频流)

8.2.2 Zstandard (zstd)

# 创建使用 zstd 的文件系统(推荐)
sudo bcachefs format /dev/sdb --compression=zstd

# 指定压缩级别(1-19,默认 3)
sudo bcachefs format /dev/sdb --compression=zstd --compression_level=3

zstd 技术指标:

级别压缩速度解压速度压缩比适用场景
1~590 MB/s~1500 MB/s~2.8:1速度优先
3 (默认)~515 MB/s~1500 MB/s~3.1:1平衡
6~350 MB/s~1500 MB/s~3.3:1压缩比优先
9~200 MB/s~1500 MB/s~3.5:1高压缩
19~15 MB/s~1500 MB/s~3.8:1极限压缩

适用场景:

  • ✅ 通用场景(推荐)
  • ✅ 文本/代码/日志
  • ✅ 虚拟机镜像
  • ✅ 数据库备份

8.2.3 Gzip

# 创建使用 gzip 的文件系统
sudo bcachefs format /dev/sdb --compression=gzip

# 指定级别(1-9,默认 6)
sudo bcachefs format /dev/sdb --compression=gzip --compression_level=6

gzip 技术指标:

级别压缩速度解压速度压缩比
1~200 MB/s~400 MB/s~2.7:1
6 (默认)~38 MB/s~400 MB/s~3.0:1
9~12 MB/s~400 MB/s~3.1:1

适用场景:

  • ✅ 需要与 gzip 格式兼容
  • ⚠️ 性能不如 zstd

8.3 压缩性能测试

8.3.1 测试脚本

#!/bin/bash
# benchmark-compression.sh

set -e

DEVICE="/dev/sdb"
MOUNT="/mnt/test"
TEST_DATA="/tmp/test-data"

# 创建测试数据
echo "创建测试数据..."
mkdir -p "$TEST_DATA"
# 文本数据
for i in $(seq 1 100); do
    cat /var/log/syslog > "$TEST_DATA/text_$i.txt" 2>/dev/null || \
    echo "This is test data line $i. " > "$TEST_DATA/text_$i.txt"
done
# 二进制数据
dd if=/dev/urandom of="$TEST_DATA/random.bin" bs=1M count=100

echo "测试数据大小: $(du -sh $TEST_DATA | awk '{print $1}')"
echo ""

# 测试不同算法
for algo in none lz4 zstd gzip; do
    echo "=== 测试算法: $algo ==="
    
    # 格式化
    sudo bcachefs format "$DEVICE" --compression="$algo" --force
    
    # 挂载
    sudo mkdir -p "$MOUNT"
    sudo mount -t bcachefs "$DEVICE" "$MOUNT"
    
    # 写入测试
    echo -n "写入时间: "
    time cp -r "$TEST_DATA" "$MOUNT/"
    
    # 读取测试
    echo -n "读取时间: "
    sync
    echo 3 | sudo tee /proc/sys/vm/drop_caches > /dev/null
    time cp -r "$MOUNT/test-data" /tmp/read-test
    
    # 空间使用
    echo "空间使用:"
    sudo bcachefs fs usage "$MOUNT" | grep -E "user:|Size:"
    
    # 清理
    sudo umount "$MOUNT"
    rm -rf /tmp/read-test
    
    echo ""
done

# 清理测试数据
rm -rf "$TEST_DATA"

echo "=== 测试完成 ==="

8.3.2 典型测试结果

算法写入速度读取速度空间占用CPU 使用
none500 MB/s600 MB/s10.0 GB~5%
lz4450 MB/s580 MB/s5.2 GB~10%
zstd (3)400 MB/s550 MB/s4.1 GB~15%
gzip (6)150 MB/s400 MB/s3.9 GB~40%

测试环境: Intel i7-12700K, NVMe SSD, 10GB 混合数据


8.4 压缩调优

8.4.1 选择压缩算法

决策树:

你的数据是什么类型?
│
├── 文本/代码/日志 → zstd (级别 3-6)
│   压缩比高,性能好
│
├── 虚拟机镜像 → zstd (级别 1-3)
│   需要平衡压缩比和写入性能
│
├── 视频/音频/已压缩数据 → none
│   已压缩数据无法进一步压缩
│
├── 数据库 → lz4 或 zstd (级别 1)
│   需要最低延迟
│
└── 混合数据 → zstd (级别 3)
    通用最佳选择

8.4.2 压缩级别调优

# 测试不同级别
for level in 1 3 6 9; do
    echo "=== zstd 级别 $level ==="
    sudo bcachefs format /dev/sdb --compression=zstd --compression_level=$level
    sudo mount -t bcachefs /dev/sdb /mnt/test
    # ... 运行基准测试 ...
    sudo umount /mnt/test
done

级别选择指南:

优先级推荐级别原因
速度优先zstd-1 或 lz4最低 CPU 开销
平衡zstd-3 (默认)最佳综合表现
压缩比优先zstd-6 或 zstd-9更小的存储占用
极限压缩zstd-19CPU 开销很大

8.4.3 在线修改压缩设置

# 挂载时指定
sudo mount -t bcachefs -o compress=zstd,compression_level=6 /dev/sdb /mnt/data

# 重新挂载修改
sudo mount -o remount,compress=lz4 /mnt/data

# 关闭压缩
sudo mount -o remount,compress=none /mnt/data

8.4.4 按目录设置压缩

# Bcachefs 支持按目录/文件设置压缩属性
# (需要内核支持)

# 设置目录的压缩属性
sudo bcachefs setattr /mnt/data/documents/ --compression=zstd
sudo bcachefs setattr /mnt/data/videos/ --compression=none

8.5 压缩与加密的交互

8.5.1 压缩和加密的顺序

正确顺序: 先压缩,后加密
┌─────────────┐     ┌─────────────┐     ┌───────────┐
│ 明文数据    │ ──→ │ 压缩        │ ──→ │ 加密      │ ──→ 磁盘
│ 100 MB      │     │ zstd → 30MB │     │ AES-256   │     30 MB
└─────────────┘     └─────────────┘     └───────────┘

错误顺序: 先加密,后压缩
┌─────────────┐     ┌─────────────┐     ┌───────────┐
│ 明文数据    │ ──→ │ 加密        │ ──→ │ 压缩      │ ──→ 磁盘
│ 100 MB      │     │ → 100 MB    │     │ 无效果    │     100 MB
└─────────────┘     └─────────────┘     └───────────┘

原因: 加密后的数据看起来像随机数据,无法压缩

8.5.2 配置建议

# Bcachefs 会自动先压缩后加密
# 只需同时指定两个选项
sudo bcachefs format /dev/sdb --compression=zstd --encrypted

# 注意: 如果数据已加密(如 GPG 文件),压缩无效

8.6 压缩监控

8.6.1 查看压缩统计

# 查看文件系统使用情况
sudo bcachefs fs usage /mnt/data

# 输出示例:
# Data:
#   user:              45.2 GiB (压缩前约 120.5 GiB)
#   压缩比:            ~2.7:1

8.6.2 实时监控

# 监控 I/O 和 CPU
iostat -x 1
top -p $(pgrep bcachefs)

# 查看压缩相关的内核统计
grep -i compress /proc/fs/bcachefs/*/options

8.6.3 评估压缩效果

#!/bin/bash
# eval-compression.sh

MOUNT="/mnt/data"

echo "=== 压缩效果评估 ==="

# 统计文件数量和实际大小
FILES=$(find "$MOUNT" -type f | wc -l)
ACTUAL_SIZE=$(du -sb "$MOUNT" | awk '{print $1}')
APPARENT_SIZE=$(du -sb --apparent-size "$MOUNT" | awk '{print $1}')

echo "文件数量: $FILES"
echo "实际占用: $(numfmt --to=iec $ACTUAL_SIZE)"
echo "逻辑大小: $(numfmt --to=iec $APPARENT_SIZE)"
echo "压缩比: $(echo "scale=2; $APPARENT_SIZE / $ACTUAL_SIZE" | bc):1"

8.7 特定数据类型优化

8.7.1 日志文件

# 日志文件压缩效果极好
# 通常压缩比 5:1 到 10:1

# 推荐: zstd 级别 6-9
sudo bcachefs format /dev/sdb --compression=zstd --compression_level=6

8.7.2 虚拟机镜像

# VM 镜像压缩效果好(大量零块)
# 但需要考虑写入性能

# 推荐: zstd 级别 1-3
sudo bcachefs format /dev/sdb --compression=zstd --compression_level=1

8.7.3 源代码

# 源代码压缩效果很好
# 通常压缩比 3:1 到 5:1

# 推荐: zstd 级别 3-6
sudo bcachefs format /dev/sdb --compression=zstd --compression_level=3

8.7.4 多媒体文件

# 已压缩格式(JPEG/MP4/H.264)无法进一步压缩
# 推荐: 不压缩

sudo bcachefs format /dev/sdb --compression=none

# 或者让 Bcachefs 自动检测(默认行为)
# 当压缩比 < 1.1 时自动跳过

8.7.5 数据库文件

# 数据库文件压缩需谨慎
# 可能影响随机读取性能

# 推荐: lz4 或 zstd 级别 1
sudo bcachefs format /dev/sdb --compression=lz4

8.8 压缩与碎片化

8.8.1 压缩对碎片化的影响

压缩可能导致更多碎片:

无压缩:
  文件 A: Block 0, 1, 2, 3 (连续)
  文件 B: Block 4, 5, 6, 7 (连续)

有压缩:
  文件 A: Block 0, 1 (压缩后变小,不连续)
  文件 B: Block 3, 4 (压缩后变小)
  
Bcachefs 的优化:
  - CoW 特性天然减少碎片
  - 后台整理会合并碎片

8.8.2 碎片整理

# 触发在线碎片整理
sudo bcachefs fs defrag /mnt/data

# 监控碎片状态
sudo bcachefs fs usage --verbose /mnt/data

8.9 压缩故障排除

8.9.1 压缩比异常低

# 检查数据类型
file /mnt/data/somefile

# 可能原因:
# 1. 数据已压缩(视频、图片、压缩包)
# 2. 数据已加密
# 3. 随机数据

# 解决: 对这类数据关闭压缩

8.9.2 CPU 使用率过高

# 检查压缩算法和级别
mount | grep bcachefs

# 可能原因:
# 1. 使用了高压缩级别(如 zstd-19)
# 2. 大量写入操作

# 解决:
# 1. 降低压缩级别
# 2. 切换到 lz4
# 3. 对部分数据关闭压缩

8.9.3 I/O 性能下降

# 监控压缩相关的 I/O
iostat -x 1

# 可能原因:
# 1. CPU 成为瓶颈(压缩/解压)
# 2. 写放大

# 解决:
# 1. 使用更快的压缩算法
# 2. 升级 CPU
# 3. 考虑关闭压缩

8.10 完整示例

混合数据环境配置

#!/bin/bash
# setup-mixed-compression.sh

DEVICE="/dev/sdb"
MOUNT="/mnt/data"

# 创建文件系统,使用 zstd 默认压缩
sudo bcachefs format "$DEVICE" --compression=zstd --compression_level=3

# 挂载
sudo mkdir -p "$MOUNT"
sudo mount -t bcachefs "$DEVICE" "$MOUNT"

# 创建目录结构
mkdir -p "$MOUNT"/{documents,logs,media,virtual-machines,backups}

# 设置不同目录的压缩策略
# 文档: 高压缩
sudo bcachefs setattr "$MOUNT/documents/" --compression=zstd 2>/dev/null || true

# 日志: 高压缩
sudo bcachefs setattr "$MOUNT/logs/" --compression=zstd 2>/dev/null || true

# 媒体文件: 不压缩
sudo bcachefs setattr "$MOUNT/media/" --compression=none 2>/dev/null || true

# 虚拟机: 快速压缩
sudo bcachefs setattr "$MOUNT/virtual-machines/" --compression=lz4 2>/dev/null || true

echo "=== 配置完成 ==="
echo "目录压缩策略:"
echo "  documents/:       zstd (高压缩)"
echo "  logs/:            zstd (高压缩)"
echo "  media/:           none (不压缩)"
echo "  virtual-machines/: lz4 (快速压缩)"
echo "  backups/:         zstd (默认)"

8.11 本章小结

算法压缩比速度CPU推荐场景
none1:1最快已压缩数据
lz4~2:1极快实时/数据库
zstd~3:1通用(推荐)
gzip~3:1兼容性需求

核心决策:

  1. 大多数场景 → zstd 级别 3
  2. 性能敏感 → lz4
  3. 存储敏感 → zstd 级别 6-9
  4. 已压缩数据 → none

扩展阅读


上一章: ← 第 7 章:快照管理 | 下一章: 第 9 章:性能调优 →