ZFS 性能:我需要在池或文件系统中保留可用空间吗?

ZFS 性能:我需要在池或文件系统中保留可用空间吗?

我知道 ZFS 的性能很大程度上取决于可用空间的数量:

将池空间利用率保持在 80% 以下,以保持池性能。目前,当池非常满且文件系统频繁更新时(例如在繁忙的邮件服务器上),池性能可能会下降。满池可能会导致性能下降,但不会出现其他问题。[...] 请记住,即使大多数静态内容的利用率在 95-96% 范围内,写入、读取和重新同步性能也可能受到影响。ZFS_Best_Practices_Guide,solarisinternals.com (archive.org)

现在,假设我有一个 10T 的 raidz2 池,托管一个 ZFS 文件系统volume。现在我创建一个子文件系统volume/test并给它预留 5T。

然后我将两个文件系统按照 NFS 安装到某个主机并执行一些工作。我知道我无法写入volume超过 5T 的数据,因为剩余的 5T 被保留给volume/test

我的第一个问题是,如果我用 ~5T 填充我的挂载点,性能会如何下降volume?它会下降吗,因为该文件系统中没有可用空间用于 ZFS 的写时复制和其他元数据?还是会保持不变,因为 ZFS 可以使用为 保留的空间内的可用空间volume/test

现在第二个问题。如果我按如下方式更改设置,会有什么不同吗?volume现在有两个文件系统,volume/test1volume/test2。两者都有 3T 的预留空间(但没有配额)。现在假设我向写入 7T test1。两个文件系统的性能是否相同,还是每个文件系统的性能都会不同?性能会下降还是保持不变?

谢谢!

答案1

是的。您需要在池中保留可用空间。它主要用于写时复制操作和快照。当利用率达到约 85% 时,性能会下降。您可以提高利用率,但肯定会产生影响。

不要乱用预留。尤其是 NFS。没必要。也许对于 zvol 来说可以,但对于 NFS 来说不行。

不过,我并不觉得有什么困惑。如果你有 10T,不要使用超过 85% 的容量。适当调整你的份额,使用配额限制其使用。或者不要使用任何配额并监控您的总体水池用法。

答案2

当您的要么非常满,要么非常碎片化。造成这种情况的原因是 ZFS 使用的空闲块发现机制。与 NTFS 或 ext3 等其他文件系统不同,没有块位图显示哪些块被占用,哪些块是空闲的。相反,ZFS 将您的 zvol 划分为(通常为 200)个称为“元块”的较大区域,并在每个元块中存储空闲块信息(空间图)的 AVL 树1。平衡的 AVL 树允许高效搜索适合请求大小的块。

虽然选择这种机制是出于规模的原因,但不幸的是,当出现高水平的碎片化和/或空间利用率时,它也变成了一个很大的麻烦。一旦所有 metaslab 都承载了大量数据,您就会获得大量小块的空闲块区域,而当池为空时,您只会获得少量的大块区域。如果 ZFS 随后需要分配 2 MB 的空间,它会开始读取和评估所有 metaslab 的空间图,以找到合适的块或将 2 MB 拆分成更小的块的方法。这当然需要一些时间。更糟糕的是,这将耗费大量的 I/O 操作,因为 ZFS 确实会读取所有空间图关闭物理磁盘。 为了任何你的写作。

性能下降可能非常显著。如果您喜欢漂亮的图片,请查看Delphix 上的博客文章其中的一些数字取自(过于简单但有效的)zfs池。我厚颜无耻地窃取了其中一张图表——看看这张图中的蓝线、红线、黄线和绿线,它们分别代表容量为 10%、50%、75% 和 93% 的池,以 KB/s 为单位绘制写入吞吐量,随着时间的推移变得碎片化: zpool 性能下降

解决这个问题的一个快速而肮脏的传统方法是metaslab 调试模式(只需echo metaslab_debug/W1 | mdb -kw在运行时发出命令即可立即更改设置)。在这种情况下,所有空间映射都将保存在 OS RAM 中,从而消除了每次写入操作时过多且昂贵的 I/O 的要求。最终,这也意味着您需要更多内存,尤其是对于大型池,因此这是一种 RAM 与存储的马戏交易。您的 10 TB 池可能需要 2-4 GB 内存2,但您将能够毫不费力地将其利用率提高到 95%。


1这有点复杂,如果你感兴趣的话,可以看看Bonwick 关于太空地图的帖子了解详情

2如果您需要一种方法来计算内存的上限,请使用zdb -mm <pool>检索segments每个 metaslab 中当前正在使用的数量,将其除以二以模拟最坏情况(每个占用的段后面都会跟着一个空闲的段),将其乘以 AVL 节点的记录大小(两个内存指针和一个值,考虑到 zfs 的 128 位性质和 64 位寻址,总和为 32 个字节,尽管出于某种原因人们似乎普遍假设 64 个字节)。

zdb -mm tank | awk '/segments/ {s+=$2}END {s*=32/2; printf("Space map size sum = %d\n",s)}'

参考:基本概要载于Markus Kovero 在 zfs-discuss 邮件列表上发布的这篇文章,尽管我相信他在计算中犯了一些错误,我希望我也能够纠正这些错误。

相关内容