使 Linux 在读取本地磁盘的同时写入网络文件系统

Mal*_*ous 17 linux io cache cifs

概括

如何将 Linux 配置为同时从本地磁盘/文件系统读取并写入网络共享,而不是在没有数据通过网络时读取,然后在本地磁盘处于传输状态时通过网络发送该数据闲置的?

同时读取和写入要快得多,而不是只执行一个操作,然后以交替方式执行另一个操作。

细节

我正在将大量数据从 Linux 机器上的本地磁盘移动到 NAS 设备。

rsync用来基本上复制/srv/data/mnt/nas,这是一个 CIFS 挂载。

它开始很好,读取速度为 100MB/秒,写入 NAS 速度为 100MB/秒(千兆网络的限制),读取和写入同时进行。

但是现在,几个小时后,我发现它正在从本地磁盘读取,然后在写入 NAS 时停止读取,然后当没有更多数据要写入 NAS 时,它恢复从磁盘读取再次。读取磁盘时网络空闲,使用网络时磁盘空闲。

不用说,读取 200MB 然后写入 200MB 比同时读取和写入 200MB 花费的时间要长得多。

如何配置内核,使其坚持早期同时读取和写入的行为,而不是在读取和写入之间交替,一次只执行一个操作?

一些观察:当本地磁盘以 100+MB/秒的速度读取时,一切似乎都并行发生,但是一旦磁盘变慢(由于某种原因,现在似乎只有 20MB/秒),这就是读取/写入的时间切换似乎发生了。

我也sync可以每隔几秒钟手动运行一次以使写入与读取并行发生(尽管显然速度降低了)但是放入sync一个while循环中使其每五秒运行一次似乎不是正确的解决方案......

内核似乎缓存了大约 1GB 的数据,然后尽可能快地通过网络将其写出 - 这很好 - 我只是不明白为什么在通过网络发送数据时需要停止读取慢速磁盘网络。

Mal*_*ous 27

经过更多调查,看起来这个问题与内核的相关性较少,而更多地rsync与 CIFS 的交互方式有关。

据我所知,发生的事情是,当rsync关闭目标文件时,CIFS(可能还有任何网络文件系统)确保文件在close系统调用返回之前完全刷新并写入远程磁盘。这是为了确保任何应用程序一旦关闭操作成功完成,文件已完全保存,并且不存在可能导致数据丢失的任何进一步错误的风险。

如果不这样做,那么应用程序可能会关闭文件,认为保存操作成功退出,然后(可能是由于网络问题)最终无法写入数据,但到那时应用程序对此做任何事情都为时已晚,例如询问用户是否要将文件保存在其他地方。

这个要求意味着每次rsync完成复制文件时,整个磁盘缓冲区必须通过网络清空,然后rsync才能继续读取下一个文件。

解决方法是使用cache=none禁用此功能的选项挂载 CIFS 共享,并使所有 I/O 直接进入服务器。这消除了问题并允许并行执行读取和写入,但是该解决方案的缺点是性能稍低。就我而言,网络传输速度从 110MB/秒下降到 80MB/秒。

这可能意味着如果您要复制大文件,交替读/写行为可能会更好地提高性能。对于许多较小的文件,禁用缓存将导致每次关闭文件时缓存刷新次数减少,因此性能可能会提高。

它似乎rsync需要一个选项来关闭另一个线程中的文件句柄,这样它就可以在最后一个文件仍在刷新时开始读取下一个文件。

编辑:我已经确认这cache=none在传输大量小文件(将其从 10MB/秒提高到 80MB/秒)时绝对有帮助,但在传输大文件(1GB+)时cache=none,传输速度从 110MB/秒下降到相同的 80MB/秒。这表明从许多小文件传输的缓慢与源磁盘查找无关,而更多的是从所有小文件中刷新了如此多的缓存。

  • 这是一个非常有趣的问题,感谢您发布解释。`rsync` 在不同的线程(实际上是不同的进程)中*读取*文件,因为它的设计使得 `rsync` 的一个副本在网络的每一侧运行,即使在你的情况下两个副本都在同一个侧(并且文件系统隐藏了存在网络的事实)。我想它没有帮助,因为读取器进程非常非常快地填满了管道,而写入器进程阻塞在 `close()` 上。如果你在网络上使用 `rsync`,而不是 CIFS,`rsync` 会表现得更好。 (2认同)
  • 可能与您的情况无关:几年前我遇到了类似的问题,将 `dump(8)` 的输出写入通过 NFS 安装的 NAS。当时我将问题诊断为 NAS 上的 CPU 最大化,因为 NFS 服务器和在 NAS 上运行的防火墙的综合影响(该框未扎根,并且无法从 NAS 上完全禁用防火墙)网页界面)。当我们用旧 PC 替换 NAS 时,问题就消失了。FWIW。 (2认同)