场景:我有两个外部硬盘,我想将其中一个作为另一个的备份。传统上,我会定期连接第二个硬盘,并 rsync 同步任何更改。ZFS 是否提供了更好的方法来实现这一点?
我认为我应该创建一个“zfs 镜像”设置,但为了方便起见,我不想一直随身携带备份驱动器,而是希望定期同步任何更改。ZFS 是否提供了执行此操作的方法,或者这不是合适的用法?如果是,那么执行此操作的典型 ZFS 方式是什么?(例如,我不想每次想要更新备份驱动器时都必须检查每个扇区是否有更改,从而对驱动器造成损害)
答案1
ZFS 在镜像驱动器离线一段时间后,增量更新的能力有限。TL;DR:您能按照您建议的方式做您要做的事情,但这不是镜子的本意。
实际上,您所建议的几乎每次都需要进行完整的重新同步,因为临时更改会导致过多的超级块修订,因此增量重新同步没有共同的基点。如果在此过程中出现故障,就您的数据而言,您很可能会陷入困境。还请记住,由于其 Merkle 树磁盘数据格式,ZFS 重新同步可以(并且确实)按照“数据重要性降低的顺序”进行,而不是像非基于文件系统的 RAID 系统那样按顺序进行。当然,这里的“数据重要性”是就 ZFS 而言的,而不是就您认为重要或值得保留的内容而言。由此产生的寻道活动很容易对单个驱动器造成重大压力。
使两个 ZFS 文件系统同步的规范方法是在zfs send | zfs receive
它们之间使用。这要求两个文件系统都可用(但您能存储 zfs send 的输出,并在稍后将其用作 zfs accept 的输入(如果你愿意的话),但你应该知道,这会带来一个巨大的警告:zfs receive
使不尝试从部分损坏的数据流中恢复,如果检测到错误则中止)。
- 每个备份驱动器都有一个池。我们称之为坦克和管道假设我们有坦克我们想要复制到管道。
- 连接两个驱动器,
zpool import
然后坦克和管道。您可以传递-N
给 zpool import 以使其不挂载任何文件系统。 - 对源文件系统进行快照,坦克。
zfs snapshot tank@current1984 -r
- 查找最近的快照坦克和管道有共同点。使用类似的东西
zfs list tank pipe -t snapshot
来获取原始列表。假设他们共同拥有的最新快照是current1948
。 - 运行类似命令,逐步传输和快照
zfs send -R -I tank@current1948 tank@current1984 | zfs receive pipe
之间的增量current1948
current1984
坦克 到管道. 阅读zfs
手册页以获取有关发送和接收子命令的更多详细信息。 - 等待该操作完成,然后可选择删除不再需要的任何快照。确保至少保留一个两个
current1984
池(更确切地说是文件系统)共有的快照(例如),以便下次用作基础。
此时,两个池将具有相同的内容,直到您使用的快照为止。如果操作正确,这也应该只需要传输差异;我无法想象增量zfs send | zfs receive
需要执行任何类似完整镜像重新同步的场景。如果您愿意,它还允许您稍后向备份池添加冗余。如果源驱动器在复制过程中发生故障,您仍然应该有旧的备份随时可用;只有您尝试传输的差异会丢失。