![将相同的数据写入 ZFS 下的文件块会占用快照中的空间吗?](https://linux22.com/image/128599/%E5%B0%86%E7%9B%B8%E5%90%8C%E7%9A%84%E6%95%B0%E6%8D%AE%E5%86%99%E5%85%A5%20ZFS%20%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%E5%9D%97%E4%BC%9A%E5%8D%A0%E7%94%A8%E5%BF%AB%E7%85%A7%E4%B8%AD%E7%9A%84%E7%A9%BA%E9%97%B4%E5%90%97%EF%BC%9F.png)
我有一个16M的文件。
我拍摄了包含它的 ZFS 文件系统的快照。
如果我用相同的数据覆盖文件,ZFS 是否需要存储文件所有块的两个副本?
答案1
是的,如果从文件集获取快照,ZFS 将为同一个文件分配额外的空间。
首先,让我们创建一个空文件集并准备一个要从中复制的文件。出于简单原因,压缩已关闭,并且池是在单个磁盘上创建的,没有任何雷兹或者镜子。
[root@localhost ~]# dd if=/dev/urandom of=/tmp/testfile bs=16M count=1
1+0 records in
1+0 records out
16777216 bytes (17 MB) copied, 0.113345 s, 148 MB/s
[root@localhost ~]# zpool create tank sdd
[root@localhost ~]# zfs create tank/test
磁盘上使用的空间可以通过 来查看zpool list
。
[root@localhost]# zpool list tank
NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
tank 9.94G 182K 9.94G - 0% 0% 1.00x ONLINE -
现在将文件复制到 ZFS 文件集,创建快照并查看使用的空间。
[root@localhost ~]# /bin/cp /tmp/testfile /tank/test/
[root@localhost ~]# zfs list -t all -r tank/test
NAME USED AVAIL REFER MOUNTPOINT
tank/test 16.0M 9.61G 16.0M /tank/test
[root@localhost ~]# zfs snapshot tank/test@1
[root@localhost ~]# zfs list -t all -r tank/test
NAME USED AVAIL REFER MOUNTPOINT
tank/test 16.0M 9.61G 16.0M /tank/test
tank/test@1 0B - 16.0M -
好的,再次将相同的文件复制到 ZFS 文件集中的相同位置,然后再次查看使用的空间。
[root@localhost ~]# /bin/cp -f /tmp/testfile /tank/test/
[root@localhost ~]# zfs list -t all -r tank/test
NAME USED AVAIL REFER MOUNTPOINT
tank/test 32.0M 9.60G 16.0M /tank/test
tank/test@1 16.0M - 16.0M -
此外,池中使用的磁盘空间增长到 32MB。
[root@localhost tank]# zpool list tank
NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
tank 9.94G 32.2M 9.91G - 0% 0% 1.00x ONLINE -
如您所见,tank/test
文件集现在总共占 32MB,其中文件集分为 16MB tank/test
,快照中分为 16MB tank/test@1
。输出还zpool list
显示磁盘上分配了 32MB。
如果你重复复制并拍摄快照USED 总量tank/test
将进一步增长。
更新
感谢@Andrew Henle 的询问。必须更新我上面的答案并将继续重复数据删除下面的东西。
让我们用一个文件集再次执行此操作重复数据删除已启用。
[root@localhost]# zfs destroy -r tank/test
[root@localhost]# zfs create tank/test-dedup
[root@localhost]# zfs set dedup=on tank/test-dedup
我将跳过此处的单个步骤,仅添加已用空间概述的输出。
[root@localhost ~]# zfs list -t all -r tank/test-dedup
NAME USED AVAIL REFER MOUNTPOINT
tank 32.3M 9.61G 24K /tank
tank/test-dedup 32.1M 9.61G 16.0M /tank/test-dedup
tank/test-dedup@1 16.0M - 16.0M -
[root@localhost ~]# zpool list tank
NAME SIZE ALLOC FREE EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
tank 9.94G 16.3M 9.92G - 0% 0% 2.00x ONLINE -
和重复数据删除启用后,快照仍报告使用额外的大小,但正如你所看到zpool list
的重复数据删除节省磁盘空间,重复数据删除率为 2。
IIRC 通常不建议使用重复数据删除,因为内存使用量很大并且会影响性能。我认为正在改进 ZFS 中的重复数据删除功能。
答案2
我知道这已经很旧了,但是(至少对于 OpenZFS 的某些版本)您可以使用以下方法避免相同块的额外分配空写
ZFS 支持每个数据块的端到端校验和。当使用加密安全校验和(并且启用压缩)时,OpenZFS 会将传入写入的校验和与现有磁盘数据的校验和进行比较,并避免对未更改的数据发出任何写入 I/O。在相同文件定期被几乎相同的数据覆盖的情况下(例如大型随机访问文件的定期完整备份),这可以帮助提高性能和快照空间使用率。