字数 1530,阅读大约需 8 分钟
Btrfs 的压缩、配额、属性是日常运维必会。本篇讲清三件套的配置、调优和踩坑。
一、压缩(Compression)
1.1 压缩算法对比
经验:zstd:3 是默认值(不显式写时用)。
1.2 启用压缩
# 挂载时启用
$ mount -o compress=zstd /dev/sdb /mnt
# remount
$ mount -o remount,compress=zstd /mnt
1.3 性能影响
误解:压缩 = CPU 开销 = 慢
事实:
- • zstd 在现代 CPU 上极快(超过磁盘 IO 速度)
- • 随机读:CPU 解压开销可见,但有 ARC 后影响小
1.4 已有数据怎么办?
挂载压缩选项后:
重压已存在数据:
# defragment + compress(会重写所有文件!)
$ btrfs filesystem defragment -r -czstd /mnt
# ^^^^-zstd 压缩
# ^^-r 递归
# ^-c 压缩
警告:这个操作会写时复制所有文件,要确保空间够。
1.5 各场景推荐
二、Quota(配额)
Btrfs 配额通过 qgroup 实现。
2.1 启用 qgroup
# 启用
$ btrfs quota enable /mnt
# 看是否启用
$ btrfs qgroup show /mnt
2.2 配额类型
# 限制"引用"(含子卷)
$ btrfs qgroup limit 5G /mnt/home
# 限制"独占"(不含子卷)
$ btrfs qgroup limit -e 5G /mnt/home
2.3 实战
# 1. 启用
$ btrfs quota enable /mnt
# 2. 给每个用户限制
$ btrfs qgroup limit 10G /mnt/home/alice
$ btrfs qgroup limit 20G /mnt/home/bob
# 3. 查看
$ btrfs qgroup show -reF /mnt
qgroupid rfer excl max_rfer max_excl
-------- ---- ---- --------- --------
0/5 16KiB 16KiB none none
0/300 1.2GiB 1.2GiB 10.00GiB 10.00GiB ← alice
0/301 800MiB 800MiB 20.00GiB 20.00GiB ← bob
2.4 qgroup 的性能问题
重要警告:Btrfs 的 qgroup 有严重的性能陷阱。
症状:
解决方案:
- • 监控:
btrfs qgroup show 看延迟
生产建议:
三、属性(Properties)
Btrfs 有 对象属性(object-level properties),比 ZFS 少一些,但够用。
3.1 挂载选项
主要属性都是挂载选项:
# /etc/fstab
UUID=... / btrfs subvol=@,compress=zstd,noatime,autodefrag 0 0
3.2 常用挂载选项
| | |
|---|
compress=algo | | zstd |
noatime | | |
nodatacow | | |
autodefrag | | |
subvol=path | | |
subvolid=N | | |
device=path | | |
degraded | | |
ro | | |
nospace_cache | | |
clear_cache | | |
commit=N | | |
space_cache=v2 | | |
usebackuproot | | |
recovery | | |
usrquota | | |
grpquota | | |
3.3 完整推荐配置
# 根分区
UUID=... / btrfs subvol=@,compress=zstd,noatime,space_cache=v2,commit=120 0 0
# 数据
UUID=... /data btrfs subvol=data,compress=zstd:3,noatime,space_cache=v2 0 0
# 数据库(关 COW,关压缩)
UUID=... /var/lib/postgresql btrfs subvol=db,nodatacow,noatime 0 0
四、CoW 与 nodatacow
4.1 CoW 控制的两种方式
4.2 nodatacow
# 挂载时
$ mount -o nodatacow /dev/sdb /mnt/db
# 整 subvolume 不 COW(写密集性能 ↑)
# 代价:失去快照、scrub 能力
4.3 chattr +C(更灵活)
# 关闭文件的 COW
$ chattr +C /mnt/db/postgresql.conf
# 看 COW 状态
$ lsattr /mnt/db/postgresql.conf
----C----- /mnt/db/postgresql.conf
# ^ C = nocow
# 恢复 COW
$ chattr -C /mnt/db/postgresql.conf
使用场景:
- • 数据库文件(MySQL InnoDB、PostgreSQL)
五、defragment(碎片整理)
5.1 何时整理
5.2 整理命令
# 整理单个文件
$ btrfs filesystem defragment /mnt/data/bigfile
# 整理整个目录
$ btrfs filesystem defragment -r /mnt/data
# 整理 + 压缩
$ btrfs filesystem defragment -r -czstd /mnt/data
注意:defragment 实际上是写时复制(把碎片文件重新连续写)。会消耗空间。
5.3 autodefrag(自动模式)
# 挂载时启用
$ mount -o autodefrag /dev/sdb /mnt
# 或
$ mount -o remount,autodefrag /mnt
不建议对所有数据启用(可能影响性能)。一般用于 reflink/稀疏文件 场景。
六、scrub(自愈)
6.1 什么是 scrub
- • 遍历所有 extent,校验 checksum
6.2 命令
# 启动 scrub
$ btrfs scrub start /mnt
# 看状态
$ btrfs scrub status /mnt
scrub status for /mnt
scrub started at Mon Jan 15 03:00:00 2024
scrub running for 02:30:00
...
data_extents_scanned: 1234567
tree_extents_scanned: 12345
data_extents_skipped: 0
data_bytes_scanned: 5.0GiB
tree_bytes_scanned: 1.2GiB
read_errors: 0
verify_errors: 0
csum_errors: 0
...
# 取消
$ btrfs scrub cancel /mnt
6.3 scrub 频率
七、设备使用情况
# 看文件系统使用
$ btrfs filesystem usage /mnt
Overall:
Device size: 10.00GiB
Device allocated: 1.50GiB
Device unallocated: 8.50GiB
Used: 1.20GiB
Free (estimated): 7.80GiB (min: 7.80GiB)
Data ratio: 1.00
Metadata ratio: 2.00
Global reserve: 3.50MiB (used: 0)
...
# 看分配
$ btrfs filesystem df /mnt
八、生成代(Generation)
# 看 generation
$ btrfs subvolume show /mnt/data
Generation: 12
# generation 是 Btrfs 的"事务号"
# 每次 commit 递增
# 损坏时用于推断
九、本篇小结
| | |
|---|
| 压缩 | zstd | |
| 配额 | | |
| nodatacow | | |
| autodefrag | | |
| scrub | | |
| mount 选项 | noatime,space_cache=v2 | |
最佳实践:
- • 挂载时启用 compress=zstd(几乎免费)