强曰为道

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

第 9 章:空间平衡 (Balance)

第 9 章:空间平衡 (Balance)

9.1 Balance 概述

9.1.1 什么是 Balance

Balance(平衡)是 Btrfs 的空间重分配操作。它重新写入文件系统中的数据块,将它们从旧的块组(Block Group)移动到新的块组,实现:

  1. 空间回收 — 删除大量数据后回收未使用的块组空间
  2. RAID 转换 — 在不同 RAID 级别之间转换
  3. 碎片整理 — 重新组织数据布局
  4. 块组合并 — 合并零散的小块组

9.1.2 块组(Block Group)

Btrfs 将设备空间划分为多个块组(Block Group),每个块组的大小通常为 1GB(数据)或 256MB(元数据):

设备 /dev/sdb(100GB)
┌──────────┬──────────┬──────────┬──────────┬──────────┐
│ Block     │ Block     │ Block     │ Block     │  未分配   │
│ Group 1   │ Group 2   │ Group 3   │ Group 4   │  空间     │
│ 数据      │ 数据      │ 元数据    │ 数据      │           │
│ 50% 使用  │ 10% 使用  │ 30% 使用  │ 已满      │           │
└──────────┴──────────┴──────────┴──────────┴──────────┘

平衡后:
┌──────────┬──────────┬──────────┬──────────┬──────────┐
│ Block     │ Block     │ Block     │ 已释放    │  未分配   │
│ Group 1   │ Group 2   │ Group 3   │ 块组      │  空间     │
│ 数据      │ 元数据    │ 数据      │           │  (更大)   │
│ 80% 使用  │ 30% 使用  │ 70% 使用  │           │           │
└──────────┴──────────┴──────────┴──────────┴──────────┘

9.1.3 何时需要 Balance

场景是否需要 Balance原因
大量删除文件后✅ 是回收空块组空间
添加新设备后✅ 是将数据重新分配到新设备
RAID 级别转换✅ 是必须通过 balance 转换
btrfs filesystem usage 显示 Unallocated 很少✅ 是空间碎片化
空间"已用"与"实际数据量"差距大✅ 是块组内有大量空闲但无法释放
日常使用❌ 否不需要定期 balance
SSD 碎片整理⚠️ 谨慎可能增加 SSD 写入量

9.2 Balance 操作

9.2.1 基础 Balance

# ⚠️ 全平衡 - 会重写所有数据,非常耗时!
sudo btrfs balance start /mnt/data

# 带过滤器的平衡(推荐)
# 只平衡使用率低于 5% 的块组
sudo btrfs balance start -dusage=5 /mnt/data

# 只平衡使用率低于 50% 的块组
sudo btrfs balance start -dusage=50 /mnt/data

# 只平衡元数据
sudo btrfs balance start -musage=10 /mnt/data

# 同时过滤数据和元数据
sudo btrfs balance start -dusage=10 -musage=30 /mnt/data

9.2.2 Balance 过滤器详解

过滤器说明示例
-dusage=N数据块组使用率 <= N%-dusage=10
-musage=N元数据块组使用率 <= N%-musage=20
-dlimit=N最多处理 N 个数据块组-dlimit=5
-mlimit=N最多处理 N 个元数据块组-mlimit=5
-dconvert=PROFILE转换数据 RAID 级别-dconvert=raid1
-mconvert=PROFILE转换元数据 RAID 级别-mconvert=raid1
-dsuspend暂停数据平衡
-msuspend暂停元数据平衡

9.2.3 查看 Balance 状态

# 查看当前 balance 状态
sudo btrfs balance status /mnt/data

# 输出示例:
# Balance on '/mnt/data' is running
#   3 out of about 100 chunks balanced (4 considered),  97% left

# 平衡完成后:
# No balance found on '/mnt/data'

9.2.4 取消 Balance

# 取消正在进行的 balance
sudo btrfs balance cancel /mnt/data

# 暂停 balance(可以稍后恢复)
sudo btrfs balance pause /mnt/data

# 恢复暂停的 balance
sudo btrfs balance resume /mnt/data

9.3 空间回收

9.3.1 空间碎片化问题

# 场景:删除了大量数据,但空间没有释放

# 查看空间使用
sudo btrfs filesystem usage /mnt/data
# Device size:                 100.00GiB
# Device allocated:             80.00GiB
# Used:                        10.00GiB    ← 实际只用了 10GB
# Free (estimated):             20.00GiB    ← 但只有 20GB 可用!

# 原因:块组已分配但内部数据已删除,块组本身不能释放

9.3.2 回收空间

# 1. 查看块组使用情况
sudo btrfs filesystem df /mnt/data
# Data, single: total=78.00GiB, used=9.00GiB
# System, DUP: total=8.00MiB, used=16.00KiB
# Metadata, DUP: total=1.01GiB, used=500.00MiB

# 2. 使用 balance 回收低使用率的块组
sudo btrfs balance start -dusage=5 /mnt/data
# 先回收使用率低于 5% 的块组(几乎为空)

sudo btrfs balance start -dusage=20 /mnt/data
# 再回收使用率低于 20% 的块组

sudo btrfs balance start -dusage=50 /mnt/data
# 最后回收使用率低于 50% 的块组

# 3. 验证空间回收效果
sudo btrfs filesystem usage /mnt/data
# Device allocated:             15.00GiB    ← 已分配减少
# Free (estimated):             85.00GiB    ← 可用空间增加

9.3.3 渐进式回收策略

#!/bin/bash
# btrfs-reclaim-space.sh - 渐进式空间回收
set -euo pipefail

MOUNT_POINT="${1:?Usage: $0 /mount/point}"

echo "=== Space before balance ==="
sudo btrfs filesystem usage "$MOUNT_POINT" | head -10

# 渐进式回收
for usage in 1 5 10 20 30 50; do
    echo ""
    echo "=== Balancing data chunks with usage <= ${usage}% ==="
    sudo btrfs balance start -dusage="$usage" -dlimit=10 "$MOUNT_POINT" 2>&1 || true
done

# 回收元数据
for usage in 1 5 10 20 30 50; do
    echo ""
    echo "=== Balancing metadata chunks with usage <= ${usage}% ==="
    sudo btrfs balance start -musage="$usage" -mlimit=10 "$MOUNT_POINT" 2>&1 || true
done

echo ""
echo "=== Space after balance ==="
sudo btrfs filesystem usage "$MOUNT_POINT" | head -10

9.4 RAID 转换

9.4.1 单设备转 RAID 1

# 1. 添加第二个设备
sudo btrfs device add /dev/sdc /mnt/data

# 2. 转换为 RAID 1
sudo btrfs balance start -dconvert=raid1 -mconvert=raid1 /mnt/data

# 3. 验证
sudo btrfs filesystem show /mnt/data
sudo btrfs filesystem df /mnt/data

9.4.2 RAID 1 转 RAID 10

# 需要至少 4 个设备
sudo btrfs device add /dev/sdd /mnt/data
sudo btrfs device add /dev/sde /mnt/data

# 转换
sudo btrfs balance start -dconvert=raid10 -mconvert=raid10 /mnt/data

9.4.3 转换进度

# 查看转换进度
sudo btrfs balance status /mnt/data
# Balance on '/mnt/data' is running
#   15 out of about 80 chunks balanced (15 considered),  81% left

# 等待完成
while sudo btrfs balance status /mnt/data | grep -q "running"; do
    sleep 10
done

9.5 Balance 性能影响

9.5.1 资源消耗

资源影响程度说明
CPU中等数据搬移和 RAID 计算
内存仅使用少量缓存
磁盘 I/O大量读写操作
时间大文件系统可能需要数小时

9.5.2 降低 Balance 影响

# 方法 1:限制处理的块组数量
sudo btrfs balance start -dlimit=5 -mlimit=5 /mnt/data

# 方法 2:只处理低使用率块组
sudo btrfs balance start -dusage=10 /mnt/data

# 方法 3:使用 ionice 降低 I/O 优先级
sudo ionice -c 3 btrfs balance start /mnt/data

# 方法 4:选择低峰期执行
# 在 cron 中设置凌晨执行

9.5.3 Balance 速度参考

场景大约速度说明
NVMe SSD200-500 MiB/s100GB: 3-8 分钟
SATA SSD100-300 MiB/s100GB: 5-15 分钟
HDD50-100 MiB/s100GB: 15-30 分钟
RAID 1 Balance更慢需要写入两个副本
RAID 转换很慢需要重写所有数据

9.6 Balance 调度

9.6.1 推荐调度策略

场景建议说明
大量删除后手动执行删除 > 20% 数据后
添加设备后手动执行立即 balance
RAID 转换手动执行按需执行
定期维护每月 1 次只处理低使用率块组
碎片整理每季度 1 次只在 HDD 上

9.6.2 定期 Balance 脚本

#!/bin/bash
# btrfs-monthly-balance.sh - 每月空间平衡
set -euo pipefail

MOUNT_POINT="/data"
LOG_FILE="/var/log/btrfs-balance.log"

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}

log "Starting monthly balance on $MOUNT_POINT"

# 渐进式回收低使用率块组
for usage in 5 10 20 30; do
    log "Balancing data: usage <= ${usage}%"
    sudo btrfs balance start -dusage="$usage" -dlimit=5 "$MOUNT_POINT" 2>&1 | tee -a "$LOG_FILE" || true
done

for usage in 5 10 20 30; do
    log "Balancing metadata: usage <= ${usage}%"
    sudo btrfs balance start -musage="$usage" -mlimit=5 "$MOUNT_POINT" 2>&1 | tee -a "$LOG_FILE" || true
done

log "Balance completed"
log "Current usage:"
sudo btrfs filesystem usage "$MOUNT_POINT" | head -8 | tee -a "$LOG_FILE"
# Cron 配置:每月 15 号凌晨 3 点
0 3 15 * * /usr/local/bin/btrfs-monthly-balance.sh

9.7 Balance 与碎片整理

9.7.1 碎片整理命令

# 对整个文件系统进行碎片整理
sudo btrfs filesystem defragment -r /mnt/data

# 对指定目录碎片整理
sudo btrfs filesystem defragment -r /mnt/data/projects

# 指定压缩算法(同时重新压缩)
sudo btrfs filesystem defragment -r -czstd /mnt/data/documents

# 限制单个文件大小(只整理大于 32MB 的文件)
sudo btrfs filesystem defragment -r -t 32M /mnt/data

# 对单个文件碎片整理
sudo btrfs filesystem defragment /mnt/data/largefile.img

9.7.2 碎片整理注意事项

设备类型是否需要碎片整理原因
SSD❌ 通常不需要SSD 随机读性能好
HDD✅ 定期执行碎片严重影响 HDD 性能
虚拟机磁盘⚠️ 谨慎可能破坏 COW 快照共享
RAID⚠️ 谨慎碎片整理触发大量写入

⚠️ 警告: 碎片整理会破坏快照的数据共享,导致快照占用大量额外空间。对有快照的子卷执行碎片整理前请三思。


9.8 本章小结

操作命令
全平衡btrfs balance start /mnt
过滤平衡btrfs balance start -dusage=10 /mnt
RAID 转换btrfs balance start -dconvert=raid1 /mnt
查看状态btrfs balance status /mnt
取消平衡btrfs balance cancel /mnt
碎片整理btrfs filesystem defragment -r /mnt

关键要点

  1. 不要轻易执行全 balance,使用过滤器控制范围
  2. 删除大量数据后需要 balance 回收空间
  3. 添加设备后需要 balance 重新分配数据
  4. Balance 有性能影响,选择低峰期执行
  5. 碎片整理会破坏快照共享,谨慎使用

扩展阅读