字数 2131,阅读大约需 11 分钟
从"能用"到"用好"。Btrfs 默认值已能工作,但要榨取最大性能与稳定性,需要理解调优原则。
一、内存与内核调优
1.1 内核版本
Btrfs 对内核版本敏感:
| |
|---|
| ⚠️ 较稳定,但 RAID5/6 仍有 issue |
| |
| |
| |
生产推荐:Linux 5.10+ LTS。
1.2 mount 选项优化
# 推荐 fstab 模板
UUID=... / btrfs subvol=@,compress=zstd:3,noatime,space_cache=v2,commit=120 0 0
| | |
|---|
compress=zstd:3 | | |
noatime | | |
space_cache=v2 | | |
commit=120 | | |
autodefrag | | |
nodatacow | | |
discard | | |
1.3 块大小(node size)
# mkfs 时指定
$ mkfs.btrfs -n 16384 /dev/sdb
# ^^^^^ node size 16KB(默认)
# 大文件系统用 32K 或 64K
$ mkfs.btrfs -n 32768 /dev/sdb
node size 影响:
二、压缩调优
2.1 算法选择
| | | |
|---|
zstd:1 | | | |
zstd:3 | | | 推荐 |
zstd:9 | | | |
zstd:15 | | | |
lzo | | | |
no | | | |
2.2 经验
# 通用:zstd:3
# 数据库:no
# 媒体:no
# 文本:zstd:5
# 容器镜像:zstd:5
# 冷数据:zstd:9
2.3 重压已有数据
# 重新压缩整个 dataset
$ btrfs filesystem defragment -r -czstd /mnt
注意:这会复制所有文件,需要足够空间。
三、scrub 调优
3.1 调速
# ionice 限制
$ ionice -c 3 btrfs scrub start /mnt
# 看状态
$ btrfs scrub status /mnt
3.2 时间窗口
- • 用
btrfs scrub cancel 紧急停止
四、性能调优参数
4.1 sysctl 调整
# /etc/sysctl.d/99-btrfs.conf
# 脏页回写
vm.dirty_ratio = 10
vm.dirty_background_ratio = 5
vm.dirty_expire_centisecs = 1500
# 文件系统 IO 队列
fs.aio-max-nr = 1048576
4.2 调度器
# HDD:mq-deadline 或 bfq
$ echo mq-deadline > /sys/block/sdb/queue/scheduler
# SSD:none 或 mq-deadline
$ echo none > /sys/block/nvme0n1/queue/scheduler
4.3 Btrfs 内部参数
# /etc/sysctl.d/99-btrfs.conf
# 内部 IO 限速
fs.btrfs.max_inline = 2048
# ↑ 内联文件最大 2KB(小文件直接存在 metadata,节省 IO)
fs.btrfs.sectorsize = 4096
# /sys/fs/btrfs/<UUID>/allocation/
# 看分配数据
五、典型场景调优
5.1 系统盘
# /etc/fstab
UUID=... / btrfs subvol=@,compress=zstd:3,noatime,space_cache=v2 0 0
UUID=... /home btrfs subvol=@home,compress=zstd:3,noatime,space_cache=v2 0 0
UUID=... /.snapshots btrfs subvol=@snapshots 0 0
# 自动快照
$ snapper -c root create-config /
$ snapper -c home create-config /home
5.2 文件服务器
# 4 盘 raid5
$ mkfs.btrfs -d raid5 -m raid1 -L files /dev/sd{b..e}
# /etc/fstab
UUID=... /data btrfs compress=zstd:3,noatime,space_cache=v2,autodefrag 0 0
# ^^^^^^^^ 顺序写多,可以接受
5.3 数据库(特殊)
# 单独子卷 + nodatacow
$ btrfs subvolume create /mnt/@db
$ chattr +C /mnt/@db
# /etc/fstab
UUID=... /var/lib/postgresql btrfs subvol=@db,nodatacow,noatime,space_cache=v2,nospace_cache 0 0
# ^^^^^^^^^ 关闭 COW
# ^^^^^^^^^^^^^^ 不缓存空间
生产数据库 仍推荐用 ext4/xfs + 硬件 RAID。
5.4 容器/虚拟化
# KVM 磁盘放 Btrfs
$ truncate -s 100G /mnt/vms/vm-001.qcow2
$ chattr +C /mnt/vms/vm-001.qcow2 # 关闭 COW
# 或用 raw
$ truncate -s 100G /mnt/vms/vm-001.raw
六、生产环境最佳实践清单
6.1 设计阶段
✅ Linux 内核 ≥ 5.10
✅ 系统盘 raid1,文件存储 raid5/6/10
✅ 压缩 zstd:3 全开(除数据库/已压缩数据)
✅ 每个业务独立 subvolume
✅ 用 /dev/disk/by-id/ 命名
6.2 配置阶段
✅ noatime,space_cache=v2
✅ commit=120 减少 commit IO
✅ autodefrag 谨慎用
✅ 数据库子卷:nodatacow,chattr +C
✅ snapper 自动拍快照(系统盘)
6.3 运维阶段
✅ 每月 scrub
✅ SMART 监控 + 早期换盘
✅ send/recv 异地备份
✅ 监控 CAP < 90%
✅ 监控 csum_errors / uncorrectable_errors
✅ 定期 trim(SSD)
6.4 应急
✅ 应急操作清单打印贴墙
✅ 维护 Btrfs 拓扑图
✅ 关键操作有 runbook
✅ 重大变更在测试环境演练
七、常见反模式
反模式 1:数据库用 COW
# ❌ 错误
$ mkfs.btrfs /dev/sdb
$ mount /dev/sdb /var/lib/mysql
# ✅ 正确
$ mkfs.btrfs -d raid10 -m raid10 /dev/sd{b..e} /mnt
$ btrfs subvolume create /mnt/@db
$ mount -o subvol=@db,nodatacow /dev/sdb /var/lib/mysql
$ chattr +C /var/lib/mysql
反模式 2:raid5/6 + 关键数据(旧内核)
# ❌ 错误(Linux 5.10 之前内核)
$ mkfs.btrfs -d raid5 /dev/sd{b..d}
# write hole 风险
# ✅ 正确
$ mkfs.btrfs -d raid10 /dev/sd{b..e}
反模式 3:滥用 qgroup
# ❌ 错误(高 IO 场景)
$ btrfs quota enable /mnt
$ btrfs qgroup limit 1G /mnt/user1
# 性能断崖式下降
# ✅ 正确(Linux 5.10+ 或非 IO 密集)
# 先测试再生产
反模式 4:不监控容量
# CAP 100% 时
# - 写入失败
# - metadata 失败
# - 业务挂
# 一定要监控 + 告警
八、性能基准测试
# 安装 fio
$ apt install fio
# 顺序读
$ fio --name=seqread --filename=/mnt/test --rw=read \
--bs=1M --size=10G --numjobs=1 --runtime=30 \
--time_based --ioengine=libaio --direct=1
# 顺序写
$ fio --name=seqwrite --filename=/mnt/test --rw=write \
--bs=1M --size=10G --numjobs=1 --runtime=30 \
--time_based --ioengine=libaio --direct=1
# 4K 随机读
$ fio --name=randread --filename=/mnt/test --rw=randread \
--bs=4k --size=5G --numjobs=4 --runtime=30 \
--time_based --ioengine=libaio --direct=1
九、Btrfs 与其他技术对比
结论:
- • Linux 桌面/服务器文件:Btrfs(Linux 内核原生)
- • RHEL / 商业版 / 极稳:LVM + ext4
- • 个人/家用 NAS:Btrfs(Linux 原生)
十、本篇小结
| |
|---|
| 内核 | |
| mount | noatime,space_cache=v2,compress=zstd:3 |
| 压缩 | |
| scrub | |
| 数据库 | |
| 生产 | |
Btrfs 的"金科玉律":
十一、教程总结
整个 Btrfs 系列教程到此结束。从概念到实战,从日常运维到故障应急,你应该已经掌握:
| |
|---|
| |
| |
| extent / COW / subvolume / snapshot | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
接下来:在测试环境动手实验。Btrfs 历史上踩过很多坑,Linux 内核版本很重要。生产部署前先在测试环境验证。
祝你成为 Btrfs 高手 🎉
附录:命令速查卡
# ===== 文件系统 =====
mkfs.btrfs /dev/sdb # 格式化
mkfs.btrfs -d raid1 -m raid1 /dev/sdb /dev/sdc # RAID1
mkfs.btrfs -L label /dev/sdb # 加 label
wipefs -a /dev/sdb # 清除签名
# ===== 挂载 =====
mount /dev/sdb /mnt # 默认挂载
mount -o subvol=data /dev/sdb /data # 挂载子卷
mount -o subvolid=256 /dev/sdb /data # 用 ID
mount -o compress=zstd,noatime,space_cache=v2 # 推荐
# ===== Subvolume =====
btrfs subvolume create /mnt/data # 创建
btrfs subvolume list /mnt # 列表
btrfs subvolume show /mnt/data # 详情
btrfs subvolume delete /mnt/data # 删除
btrfs subvolume snapshot /mnt/data /snap1 # 可写快照
btrfs subvolume snapshot -r /mnt/data /snap1 # 只读快照
# ===== 设备管理 =====
btrfs device add /dev/sdc /mnt # 加盘
btrfs device remove /dev/sdc /mnt # 删盘
btrfs device remove missing /mnt # 删 missing
btrfs replace start /dev/sdb /dev/sdb_new /mnt # 换盘
btrfs device stats /mnt # 错误统计
btrfs device usage /mnt # 占用
# ===== Balance =====
btrfs balance start /mnt # 平衡
btrfs balance start -dconvert=raid1 /mnt # 转 RAID1
btrfs balance start -dusage=80 /mnt # 限制使用率
btrfs balance pause /mnt
btrfs balance resume /mnt
btrfs balance cancel /mnt
btrfs balance status /mnt
# ===== Scrub =====
btrfs scrub start /mnt
btrfs scrub status /mnt
btrfs scrub cancel /mnt
btrfs scrub resume /mnt
# ===== 配额 =====
btrfs quota enable /mnt
btrfs quota disable /mnt
btrfs qgroup limit 5G /mnt/data
btrfs qgroup show /mnt
# ===== 监控与维护 =====
btrfs filesystem show /mnt # 概览
btrfs filesystem df /mnt # 空间
btrfs filesystem usage /mnt # 详细
btrfs filesystem defragment -r -czstd /mnt # 重压
btrfs filesystem du -s /mnt/* # 看大小
btrfs inspect-internal dump-super /dev/sdb # 看 superblock
# ===== send/recv =====
btrfs subvolume snapshot -r /mnt/data /snap1
btrfs send /snap1 | btrfs receive /backup
btrfs send -p /snap1 /snap2 | btrfs receive /backup # 增量
# ===== 救援 =====
btrfs rescue super-recover /dev/sdb # 恢复 superblock
btrfs rescue zero-log /dev/sdb # 清 log
btrfs rescue fix-device-size /dev/sdb # 修设备大小
btrfs rescue chunk-recover /dev/sdb # 恢复 chunk
btrfs rescue clear-ino-cache /dev/sdb
# ===== snapper =====
snapper -c root create-config /
snapper -c root list
snapper -c root create --description "..."
snapper -c root delete 1-5
snapper -c root undochange 1..0