![在 NFS 共享内复制文件是否涉及网络?](https://linux22.com/image/686083/%E5%9C%A8%20NFS%20%E5%85%B1%E4%BA%AB%E5%86%85%E5%A4%8D%E5%88%B6%E6%96%87%E4%BB%B6%E6%98%AF%E5%90%A6%E6%B6%89%E5%8F%8A%E7%BD%91%E7%BB%9C%EF%BC%9F.png)
我假设使用以下方式复制 NFS 共享中的文件:
流程一:
- 客户端请求从 NFS 共享复制数据(如果没有缓存),并且数据块被异步复制到 NFS 客户端的内存中,然后客户端再次将其异步发送到 NFS 文件器以复制到新位置。
- NFS 文件程序在内存中异步接收数据块并将其写入新位置。
- 在这个过程中,虽然读取和写入的时候都有网络的参与,但是由于读写是异步的,所以一次整体读写操作的延迟会和整体数据的读写操作的延迟相同。
因此,从本地硬盘读取并写入 NFS 与从 NFS 读取并写入 NFS 几乎相同。
第一步,如果缓存已经存在,读取会非常快。
流程2:
- 客户端发送请求以启动到 NFS 服务器的数据复制操作,以及它必须从哪里读取以及必须写入的位置(似乎不是)。
- 服务器使用自己的内存完成其余的读写操作。
因此,无需网络参与。因此,可以获得更好的性能(除非网络端没有延迟)但这可能不是办法。
如果我错了,请随时纠正我。
另外,内存是否涉及每个操作,我的意思是当它通过网络发送数据时,数据首先从磁盘发送到内存(数据缓冲区),然后从内存(数据缓冲区)发送到数据缓冲区(在网络的另一端),但不是从数据缓冲区发送到网络另一端的磁盘,对吗?
答案1
NFSv4.2 确实有一个卸载复制操作,它可以在不通过客户端代理数据的情况下进行服务器到服务器的复制。现代 Linux 内核 (> 3.13?) 支持此功能。我不知道其他服务器的情况。
更新
由于 Linux 内核 4.7,Linux 服务器不支持服务器端复制 https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/fs/nfsd/nfs4xdr.c?id=refs/tags/v4.7-rc6#n1797
更新2
在内核版本 5.6 中,服务器端副本被添加到 NFSD 实现中
答案2
此"copy a file"
操作不是基本文件系统操作,例如read
、write
、open
、close
和类似操作。请参阅此页面有很好的解释文件系统必须支持的操作。
这就是所有文件系统 — — 无论是ext4
、btrfs
还是nfsv4
。
请注意,没有办法知道为什么一个进程打开文件 A、打开文件 B、从文件 A 读取,然后写入文件 B。因此,一般来说,没有办法“短路”并优化文件的复制,以便在文件 A 和文件 B 都在 NFS 文件系统上的情况下,数据不必两次跨越网络,即使它们是从同一个 NFS 服务器共享的。
许多操作系统确实提供了系统调用例如sendfile()
,它确实通过消除在用户空间之间复制数据的需要来高效地复制数据,并且理论上可以在文件系统级别复制文件,但即便如此,也必须有类似于操作的限制rename()
- 这种假设的copyfile()
操作可能必须仅限于短路单个文件系统内的那些副本。否则会造成复杂的混乱 - 如果文件 A 和文件 B 位于同一个 NFS 服务器上,客户端想要从一个复制到另一个,但文件 A 在 ext4 文件系统上,而文件 B 在另一个 XFS 文件系统上,该怎么办?