概括
如何将 Linux 配置为同时从本地磁盘/文件系统读取数据并写入网络共享,而不是在没有数据通过网络传输时读取数据,然后在本地磁盘可用时通过网络发送数据闲置的?
同时读取和写入比仅执行一个操作然后以交替方式执行另一个操作要快得多。
细节
我正在将大量数据从 Linux 计算机上的本地磁盘移动到 NAS 设备。
我用来rsync
基本上复制/srv/data
到/mnt/nas
CIFS 安装。
一开始表现不错,读取速度为 100MB/秒,写入 NAS 的速度为 100MB/秒(千兆网络的限制),并且读取和写入同时进行。
但是现在,几个小时后,我发现它正在从本地磁盘读取,然后在写入NAS时停止读取,然后当没有更多数据可写入NAS时,它恢复从磁盘读取再次。读取磁盘时网络空闲,使用网络时磁盘空闲。
不用说,读取 200MB 然后写入 200MB 比同时读取和写入 200MB 花费的时间要长得多。
如何配置内核,使其坚持同时读取和写入的早期行为,而不是在读取和写入之间交替,一次只执行一项操作?
一些观察结果:当本地磁盘以 100+MB/秒的速度读取时,一切似乎都并行发生得很好,但是一旦磁盘速度减慢(由于某种原因,现在似乎只有 20MB/秒),那就是读/写的时候切换似乎发生了。
我还可以sync
每隔几秒手动运行一次,以使写入与读取并行发生(尽管显然速度降低),但是放入sync
循环while
以使其每五秒运行一次似乎不是正确的解决方案......
内核似乎缓存了大约 1GB 的数据,然后尽快通过网络将其写出 - 这很好 - 我只是不明白为什么在数据通过网络发送出去时需要停止读取慢速磁盘网络。
答案1
经过更多调查后,这个问题似乎与内核相关较少,更多的是rsync
与 CIFS 如何交互有关。
据我所知,发生的情况是,当rsync
关闭目标文件时,CIFS(可能还有任何网络文件系统)会确保在close
系统调用返回之前文件完全刷新并写入远程磁盘。这是为了向任何应用程序保证,一旦关闭操作成功完成,文件就已完全保存,并且不存在可能导致数据丢失的任何进一步错误的风险。
如果不这样做,那么应用程序可能会关闭文件,认为保存操作成功而退出,然后(可能由于网络问题)数据最终无法写入,但到那时对于应用程序来说,采取任何措施都为时已晚,例如询问用户是否要将文件保存在其他地方。
此要求意味着每次rsync
完成文件复制后,必须通过网络清空整个磁盘缓冲区,然后rsync
才能继续读取下一个文件。
解决方法是使用禁用此功能的选项来挂载 CIFS 共享cache=none
,并使所有 I/O 直接进入服务器。这消除了问题并允许读取和写入并行执行,但该解决方案的缺点是性能稍低。就我而言,网络传输速度从 110MB/秒下降到 80MB/秒。
这可能意味着,如果您要复制大文件,交替读/写行为的性能可能会更好。对于许多较小的文件,禁用缓存将导致每次关闭文件时更少的缓存刷新,因此性能可能会提高。
似乎rsync
需要一个选项来关闭另一个线程中的文件句柄,以便它可以在最后一个文件仍在刷新时开始读取下一个文件。
编辑:我已经确认,cache=none
在传输大量小文件时(将其从 10MB/秒提高到 80MB/秒)绝对有帮助,但在传输大文件(1GB+)时,cache=none
传输速度会从 110MB/秒下降到相同的 80MB/秒。这表明来自许多小文件的缓慢传输与源磁盘查找无关,而更多地与来自所有小文件的大量缓存刷新有关。