我已经测试了两台主机之间的 10Gbit 连接,以便能够从 host1 读取 10GB 文件并使用 netcat 将其写入 host2,速度为 410MB/s。
当我通过相同的专用 10Gbit 连接再次使用 netcat 进行 ZFS 发送/接收时,我只能获得 70MB/s。快照为 2.5TB,包含 1500 万个文件。
问题
造成这种速度减慢的原因是什么?瓶颈在于回滚包含如此多文件的快照需要花费大量时间,还是文件数量对 ZFS 回滚速度没有影响?
更新
在 10GB 文件传输测试中,我获得了 410MB/s,我想这模拟了带回滚的 ZFS 发送/接收。因此,基于这一假设,我很惊讶看到速度如此不同。我使用速度来比较两个测试,因此我不必生成包含随机数据的 2.5TB 文件。
所以我不明白为什么“从主机 1 读取文件,用 netcat 传输,将文件写入主机 2”比“zfs 从主机 1 发送快照,用 netcat 传输,ZFS 在主机 2 上接收/回滚”快得多。
也许另一种询问同样问题的方式是:
如果我有两个大小相同的 2.5TB 快照,其中快照 1 包含 1 个文件,快照 2 包含 1500 万个文件。两者的执行时间是否zfs receive
相同?或者其中一个会比另一个更快?
答案1
zfs send/recv 流中涉及的文件和目录数量应该不会对其传输速度产生直接影响。但可能会间接影响,因为通常来说,随着目录/文件的增多,数据集在磁盘上的“分布”会更高,具体取决于生成它们的工作负载。这很重要,因为对于硬盘来说,顺序读取比随机读取要容易得多——如果所涉及的流遍布整个磁盘,则随机读取工作负载将远远大于顺序读取。
此外,据我了解,ZFS 文件系统(而不是 zvols)上的文件涉及 ZFS 元数据;我没有直接的数字,但对于单个 2.5 TB 文件,总体而言,与其关联的元数据块明显少于包含 1500 万个文件的 2.5 TB 文件,我并不感到惊讶。这些(可能很多)额外的元数据块将添加更多必须读取的数据,因此需要进行更多的磁盘读取(并可能进行更多搜索)。因此,是的,间接地,由 1500 万个文件组成的发送流可能比由相同大小的单个文件组成的发送流创建速度更慢(尤其是如果该文件是一次性创建的,作为顺序写入,在当时有大量连续可用空间的池中)。
ZFS 发送/接收流在未缓冲的情况下发送时,性能很不稳定,这种情况很常见 - 有时它们似乎运行得很快,然后在很长一段时间内会降至几乎为零。互联网上的各种论坛已经对这种行为进行了描述,甚至进行了某种程度的分析,所以我就不多说了。总的来说,虽然 ZFS 可以而且应该做一些工作来使其内部工作流程更高效,但许多问题的“快速修复”是在发送和接收端引入缓冲区。为此,最常用的工具是“mbuffer”。
如果底层问题可以通过添加缓冲区来解决,那么通过在 netcat 之前通过 mbuffer 传输 zfs send(并在 zfs recv 之前再次通过 mbuffer 传输),您应该会看到明显的改善。Alasdair 在他的博客上对此进行了简要的描述——我目前没有关于这个主题的任何发布,所以我将向您指出他的:http://blogs.everycity.co.uk/alasdair/2010/07/using-mbuffer-to-speed-up-slow-zfs-send-zfs-receive/
答案2
速度差异如此之大的原因在于传输文件和快照是无法比较的。文件是顺序 I/O,而快照是随机 I/O,因为它包含已更改的块。