OpenZFS 存储池、快照、校验与异地复制完整指南
OpenZFS 将卷管理、文件系统、校验、快照、压缩、克隆和复制整合在一起。它能检测静默损坏并在存在冗余时修复,但并不会自动消除所有硬件、误操作和灾难风险。生产运维必须理解 Pool、VDEV、RAIDZ、ARC、SLOG、Scrub、Snapshot、Send/Receive 和备份边界。
ZFS Pool 拓扑通常不能随意重构。错误添加单盘 VDEV、误执行 Destroy、
zfs receive -F或替换错盘都可能造成不可恢复损失。操作前必须确认设备序列号、拓扑、快照和外部备份。
一、核心层次
Pool
├─ Data VDEV(Mirror / RAIDZ / 单盘)
├─ Special VDEV(可选)
├─ SLOG(可选)
├─ L2ARC(可选)
└─ Spare(可选)
↓
Dataset / Zvol
Pool 将多个 VDEV 聚合,数据条带分布到各 Data VDEV。任何关键 Data VDEV 完全丢失都可能导致整个 Pool 丢失,因此冗余在 VDEV 内实现。
二、Mirror 与 RAIDZ
- Mirror:随机 IOPS 和重建速度好,容量效率较低;
- RAIDZ1:单校验,现代大盘重建风险较高;
- RAIDZ2:双校验,常用于通用存储;
- RAIDZ3:三校验,适合更大盘组或高风险场景。
选择依据:工作负载、盘容量、重建时间、可容忍故障和备份。不要只按可用容量最大化。
三、VDEV 宽度与扩展
传统扩容常通过增加新的完整 VDEV 实现。新旧 VDEV 不会立即自动均衡已有数据,后续写入才逐步使用新空间。某些版本支持 RAIDZ Expansion,但上线前必须核对版本、限制、性能和操作时间。
最危险误区:向已有 Mirror/RAIDZ Pool 添加一个单盘顶层 VDEV。这个单盘成为整个 Pool 的单点故障。
zpool status -P
zpool list
zpool get all tank
四、磁盘标识与换盘
使用稳定的 /dev/disk/by-id,记录槽位、序列号、WWN 和控制器映射。换盘前通过 zpool status -P、SMART、机柜标签和指示灯交叉确认。
smartctl -a /dev/disk/by-id/<disk>
zpool offline tank <old-device>
zpool replace tank <old-device> <new-device>
zpool status tank
是否先 Offline 取决于故障状态和冗余余量。不要同时拔出不确定的多块盘。
五、校验与自愈
ZFS 为数据和元数据保存校验和。读取时发现损坏,在有健康冗余时可用正确副本修复。没有冗余时只能检测,不能凭空恢复。
ECC 内存、稳定控制器和数据路径仍很重要。校验不能替代备份,也不能防止应用写入错误内容。
六、Scrub
Scrub 顺序读取数据,验证校验和并修复可修复错误。
zpool scrub tank
zpool status tank
zpool scrub -s tank
周期按容量、硬件和业务窗口制定。Scrub 会产生大量 I/O,需监控业务 P99、设备温度、错误和完成时间。Scrub 结束后必须检查状态,而不是只确认任务启动。
七、Dataset 设计
按工作负载、快照、配额、复制和权限边界创建 Dataset:
zfs create tank/database
zfs create tank/files
zfs set compression=lz4 tank/files
zfs set quota=5T tank/files
不要把所有数据放根 Dataset。独立 Dataset 便于设置 Recordsize、Mountpoint、Snapshot 和保留。
八、Recordsize 与 Volblocksize
recordsize 影响文件数据块上限;Zvol 使用 volblocksize。数据库通常需要结合数据库页、压缩和写入模式测试,不能机械设置 8K/16K。
块过大可能放大小随机写,过小增加元数据和压缩开销。创建后改变不会自动重写旧数据。
九、压缩与去重
LZ4/ZSTD 压缩常能减少 I/O 与空间,适合多数工作负载。使用真实数据验证 CPU 与压缩率。
ZFS Dedup 会消耗大量内存和元数据,除非经过容量建模与基准测试,不建议默认开启。关闭后也不会自动还原已有去重块。
十、ARC 与内存
ARC 是内存缓存。Linux 上看到 ZFS 使用大量内存并不一定是泄漏,但系统还需为应用、内核和写入缓存保留空间。
观察 ARC 命中、大小、回收、系统内存和 Swap。数据库双重缓存场景需通过测试设置上限,不要仅按网上固定比例。
十一、L2ARC
L2ARC 使用 SSD 扩展读缓存,适合工作集大于内存且具有重复读取。它不能提升所有负载,也不保存脏写数据。
L2ARC 需要 ARC 元数据和填充带宽。先分析 ARC Miss 与读取模式,再决定是否添加。
十二、ZIL 与 SLOG
ZIL 用于同步写意图日志;独立 SLOG 只是将 ZIL 放在低延迟设备上。它不是通用写缓存,也不会加速异步写。
SLOG 设备应低延迟、具备断电保护和适当冗余。设备故障行为与所用版本、Pool 状态有关,应测试而不是假设。
十三、Special VDEV
Special VDEV 可存元数据和可选小块,提升大量小文件工作负载。但它属于关键 Pool 拓扑,丢失可能导致 Pool 损坏,必须与 Data VDEV 同等级或更高冗余。
不要把单块消费级 SSD 当成可丢失缓存添加为 Special VDEV。
十四、同步写与应用语义
sync=disabled 会让请求提前返回,断电可能丢失应用认为已提交的数据。数据库、虚拟化和 NFS 场景不能为跑分随意关闭同步语义。
先优化设备、SLOG、网络和应用,再评估参数。性能不能以破坏持久性承诺为代价。
十五、快照与克隆
快照最初几乎不占空间,随着原数据变化会保留旧块。
zfs snapshot tank/database@before-upgrade
zfs list -t snapshot
zfs clone tank/database@before-upgrade tank/test-clone
快照不是独立备份:Pool 丢失、管理员误删或勒索获得同等权限时,快照也可能丢失。
十六、回滚风险
zfs rollback 会丢弃快照后的变更,递归/强制选项还可能删除后续快照。执行前使用克隆或复制在隔离位置验证,记录将丢失的数据范围。
对数据库应先保证应用一致性,不能在数据库运行中随意回滚底层 Dataset。
十七、Send 与 Receive
zfs snapshot tank/data@day1
zfs send tank/data@day1 | ssh backup zfs receive -u backup/data
zfs snapshot tank/data@day2
zfs send -i tank/data@day1 tank/data@day2 \
| ssh backup zfs receive -u backup/data
增量复制要求双方保留共同快照或源端 Bookmark。目标最好只读,避免写入导致增量接收冲突。
十八、复制选项与风险
-R:复制层级、属性和快照;-c:发送压缩块;-w:Raw Send 加密数据;-s:接收端保存中断状态;-F:回滚/删除目标不匹配数据,具有破坏性;-n -v:预演与估算。
大规模传输先预演,限制带宽,并监控源/目标容量。中断后使用 Resume Token 恢复,避免从头重传。
十九、原生加密
Dataset 可启用原生加密。密钥丢失意味着数据无法恢复。备份密钥、加载流程、轮换和灾备,限制密钥访问。
Raw Send 可让备份端保存密文而不持有密钥,适合不信任的备份位置,但恢复仍需要原密钥。
二十、容量与快照治理
快照、克隆和保留会让“删除文件但空间不释放”。排查:
zfs list -o space -r tank
zfs get usedbysnapshots,usedbydataset,usedbychildren tank/data
zfs list -t snapshot -o name,used,creation
设置 Dataset 配额、预留和快照保留,避免单个租户吃满 Pool。Pool 应保留充足空闲空间供 CoW 和重建。
二十一、常见故障
DEGRADED
查看具体 VDEV、READ/WRITE/CKSUM、SMART、链路和控制器。确认冗余后再换盘。
Pool 无法导入
检查设备可见、导入历史、主机 ID、加密密钥和错误。强制导入、回退事务组等高级操作应先复制介质并咨询专业支持。
性能下降
检查容量、碎片、ARC、Sync、设备延迟、Scrub/Resilver、Recordsize 和工作负载变化。
Resilver 很慢
检查设备健康、业务竞争、控制器、链路和 Pool 空间。不要在重建中继续增加高风险操作。
二十二、监控告警
监控 Pool 状态、VDEV 错误、SMART、容量、碎片、Scrub/Resilver、设备延迟、ARC、SLOG、温度、快照增长、复制延迟和最近可恢复点。
二十三、上线清单
- VDEV 拓扑与容错目标匹配;
- 设备使用稳定 ID 和槽位记录;
- Dataset 按工作负载拆分;
- Recordsize/压缩/同步语义经过测试;
- Special/SLOG 具备正确冗余和断电保护;
- Scrub 周期与告警生效;
- 快照有保留和容量治理;
- Send/Receive 中断恢复与异地接管完成演练;
- 加密密钥有独立安全备份;
- ZFS 冗余之外仍有独立备份。
参考资料
- OpenZFS Documentation:
https://openzfs.github.io/openzfs-docs/ - ZFS Send and Receive:
https://openzfs.github.io/openzfs-docs/Basic%20Concepts/Operations/Send%20and%20Receive.html - OpenZFS Man Pages:
https://openzfs.github.io/openzfs-docs/man/