zfs dedup开启后系统卡死或oom,根本原因是ddt全量驻留内存,每1kb数据块至少消耗320字节内存,且按预期最大去重规模预分配,而非按实际使用量动态分配。

ZFS dedup 开启后为什么系统突然卡死或 OOM?
根本原因是 dedup 表(DDT)全量驻留内存,且每 1KB 数据块至少消耗 320 字节内存(64 位系统),实际开销常达 1.2–1.5 GiB RAM / GiB 重复数据。这不是“用多少算多少”,而是按预期最大去重规模预分配——哪怕你只写了 100MB 数据,只要 ZFS 预估未来会 dedup 10TiB,它就可能提前锁住 12 GiB 内存。
-
zpool status -D显示的Dedup Ratio是事后统计值,不反映当前 DDT 内存占用;真正要看的是arcstats::ddt_memory_bytes(需kstat -p arcstats::ddt*) - 启用
dedup=on后首次写入高峰会触发 DDT 构建,此时 CPU 和内存带宽双高,zpool iostat -v 1可见DEDUP列持续非零 - 不要依赖
vdev cache或 L2ARC 缓解——DDT 本身不缓存,必须常驻主存;SSD 加速对 DDT 构建阶段几乎无帮助
sha256 和 edonr 哪个更适合 dedup?
edonr 在理论吞吐上比 sha256 快约 2–3 倍(尤其在 AVX2 指令集 CPU 上),但实际 dedup 性能差异常被 I/O 或内存带宽掩盖。关键区别不在速度,而在碰撞概率与硬件兼容性:
-
sha256是密码学安全哈希,碰撞概率 ≈ 2⁻²⁵⁶,ZFS 默认选择,兼容所有平台 -
edonr(Edon-R 512)非密码学标准,碰撞概率高约 10¹⁰ 倍(仍极低,但非零),且部分旧内核(如 Ubuntu 20.04 自带的 ZFS 0.8.x)未启用其优化路径,反而比sha256慢 - 实测建议:若用较新内核(ZFS 2.1+)且 CPU 支持 AVX2,
edonr可降低约 5–10% CPU 使用率;否则直接选sha256,省心且无兼容风险
如何安全地试水 dedup 而不炸掉系统?
别直接 zfs set dedup=on pool/dataset。ZFS 不支持运行时关闭 dedup,一旦开启,后续只能 destroy + restore。
- 先用
zdb -S poolname估算现有数据重复率——若Dedup Ratio - 小范围测试:新建临时 dataset,
zfs create -o dedup=sha256 pool/test,仅往里写 1–2 GiB 高重复数据(如多份相同 ISO 镜像),再查kstat -p arcstats::ddt_memory_bytes - 强制限制 DDT 内存上限:启动时加内核参数
zfs:zfs_dedup_prefetch_limit=1073741824(1GiB),或运行时写/sys/module/zfs/parameters/zfs_dedup_prefetch_limit(需 root)
替代 dedup 的更实用方案有哪些?
99% 的场景下,refreservation + snapshot + send/receive 手动去重,比全局 dedup 更可控、更低开销。
- 对备份类数据:用
zfs send -R -i做增量快照传输,天然跳过重复块,不占额外内存 - 对虚拟机镜像:用
zfs clone替代复制,写时复制(COW)机制已实现逻辑去重 - 真需要自动去重:考虑用户态工具如
borgbackup或restic,它们在应用层做 chunking + dedup,内存可控、可暂停、可删除
ddt_memory_bytes 一旦涨上去,除非重启或 zpool export/import,否则不会自动释放——这点最容易被忽略。










