用 ZFS 快照做即时回滚 + zfs send 增量异地备份

ZFS 的两个杀手特性:

  1. 快照即时 + 几乎零成本:copy-on-write,秒级、不占额外空间
  2. zfs send / receive:增量传输到另一台机器,做异地备份

下面在 Ubuntu 上装 ZFS、建池、配快照轮转、做远程增量备份。

1. 装 ZFS(Ubuntu 已带)

sudo apt install -y zfsutils-linux
zfs version

CentOS / RHEL:用 zfs-fuse 不行,要装 native(zfsonlinux 仓库)。

2. 建池

假设有两块裸盘 /dev/sdb /dev/sdc

# 镜像(mirror = RAID1)
sudo zpool create tank mirror /dev/sdb /dev/sdc

# 单盘
# sudo zpool create tank /dev/sdb

# RAIDZ1 (RAID5 类似,需 ≥ 3 盘)
# sudo zpool create tank raidz /dev/sdb /dev/sdc /dev/sdd

sudo zpool status tank
sudo zpool list
sudo zfs list

tank 是池名。建议用块设备的 /dev/disk/by-id/... 而不是 /dev/sdb(重启后顺序变)。

3. 创建文件系统(dataset)

sudo zfs create tank/data
sudo zfs create tank/data/users
sudo zfs create tank/data/projects

sudo zfs list
# tank/data            96K  3.5T  ...
# tank/data/users      96K  3.5T  ...
# tank/data/projects   96K  3.5T  ...

dataset 像目录但每个都是独立挂载 + 独立 properties。

4. 重要 properties

sudo zfs set compression=lz4 tank          # 透明压缩,几乎免费
sudo zfs set atime=off tank                # 关 atime,性能 +
sudo zfs set xattr=sa tank                 # 高效 xattr 存储
sudo zfs set recordsize=1M tank/data       # 大文件场景调大
sudo zfs set quota=500G tank/data/users    # 限制使用空间
sudo zfs set reservation=100G tank/data/projects   # 保留 100G

compression=lz4 是 ZFS 最值得开的:CPU 开销几乎为零,能压缩出 30-50%
的额外空间。

5. 快照

sudo zfs snapshot tank/data@$(date +%F-%H%M%S)
sudo zfs list -t snapshot
# tank/data@2026-05-23-090000   0B  ...

@ 后面是快照名。

恢复某个文件:

ls /tank/data/.zfs/snapshot/2026-05-23-090000/
# 像普通目录,cp 出来即可

整个 dataset 回滚到某快照:

sudo zfs rollback tank/data@2026-05-23-090000
# 注意:会丢掉快照之后的所有改动!

删快照:

sudo zfs destroy tank/data@2026-05-23-090000

6. 自动快照轮转:zfs-auto-snapshot

sudo apt install -y zfs-auto-snapshot

自动每 15 分钟 / 小时 / 天 / 周 / 月做快照并轮转:

ls /etc/cron.*/zfs-auto-snapshot
# /etc/cron.d/zfs-auto-snapshot   (15min)
# /etc/cron.hourly/zfs-auto-snapshot
# /etc/cron.daily/...
# ...

# 给特定 dataset 关掉某频率
sudo zfs set com.sun:auto-snapshot:frequent=false tank/data/projects
sudo zfs set com.sun:auto-snapshot:hourly=true   tank/data/projects

默认保留:96 frequent / 24 hourly / 31 daily / 8 weekly / 12 monthly。

7. zfs send:远程增量备份

第一次全量:

# 源机
sudo zfs snapshot tank/data@base
sudo zfs send tank/data@base | ssh backup@remote 'zfs receive -F tank-backup/data'

# 远端
zfs list
# tank-backup/data

之后增量:

# 源机:在前一个快照基础上做新快照
sudo zfs snapshot tank/data@2026-05-23

# 增量 send:只传 base → 2026-05-23 的差异
sudo zfs send -i tank/data@base tank/data@2026-05-23 \
  | ssh backup@remote 'zfs receive tank-backup/data'

# 完成后 base 可以删掉(远端也跟着删),用新快照做下一次的 base

实际生产用 syncoid
zrepl 包装,自动管 base 和 retention:

sudo apt install -y sanoid
# /etc/sanoid/sanoid.conf 配置 dataset + retention
# /etc/sanoid/syncoid.conf 配置 replication

syncoid tank/data backup@remote:tank-backup/data

8. 加密

# 建 dataset 时启用加密
sudo zfs create -o encryption=on -o keyformat=passphrase \
  tank/data/sensitive

# 之后挂载要解锁
sudo zfs load-key tank/data/sensitive   # 输入密码
sudo zfs mount tank/data/sensitive

zfs send / receive 加 -w 直接发加密 stream(远端不需要密码,
压缩 + dedup 在加密状态下做)。

9. 校验 + scrub

sudo zpool scrub tank
sudo zpool status tank
# scan: scrub in progress since ...
# 100M scanned out of 50G at 200M/s

scrub 读全部数据 + 校验 checksum,发现损坏自动从镜像 / parity 修复。
推荐每月跑一次:

0 3 1 * * /sbin/zpool scrub tank

10. 容量监控

sudo zpool list -v tank
# NAME      SIZE  ALLOC   FREE  ...
# tank      4T    1.2T    2.8T  ...
#   mirror  4T    1.2T    2.8T
#     sdb        -        -    -
#     sdc        -        -    -

sudo zfs list -o name,used,avail,refer,mountpoint

ZFS 超过 80% 使用率性能急剧下降;保持在 80% 以下。

踩过的坑

  • /dev/sdb 直接建池,机器重启 sdb 变成 sdc → 池找不到。永远用
    /dev/disk/by-id/ 路径。
  • ZFS 内存吃得多:1GB / 1TB 数据是经验值。8GB 机器跑 32TB 池可能要
    zfs_arc_max 限制 ARC 缓存。
  • zfs destroy 没确认就执行,整个 dataset + 所有快照消失。养成
    -n 模拟先看的习惯。
  • snapshot 是 read-only,但占空间 = 这个快照后所有被修改的数据。
    长期保留快照 + 高频改动 = 池快速胀满。retention 不要太长。
精确评价 共 0 人评价
可复现性
可复现 · 0 不可复现 · 0
文风
文风流畅 · 0 文风晦涩 · 0
立场
支持 · 0 反对 · 0

登录后即可对本帖作出评价。

评论区 0 条 · 所有人可在此交流

登录后参与评论。

还没有评论,来说两句。