我有一个 Debian squeeze (2.6.32-5-amd64),它同时是 NFS4 服务器和客户端(它通过 NFS4 自行挂载)。直接指向磁盘的本地目录是/nfs4exports/mydir
,而/nfs4mounts/mydir
通过 NFS 挂载的目录是 ,使用机器的外部 IP 地址。以下是 中的一行fstab
:
192.168.1.75:/mydir /nfs4mounts/mydir nfs4 soft 0 0
我有一个应用程序可以写入许多小文件。如果我直接写入/nfs4exports/mydir
,它每秒会写入数千个文件;但如果我写入/nfs4mounts/mydir
,它每秒会写入 4 个文件左右。如果我将写入添加到,则可以大大提高速度async
。/etc/exports
(将单个大文件写入 NFS 挂载目录的速度超过 100 MB/s。)
我检查了服务器统计信息,发现每当写入文件时,它都会被“提交”(这也会发生在 NFSv3 中):
root@debianvboxtest:~# mount -t nfs4 192.168.1.75:/mydir /mnt
root@debianvboxtest:~# nfsstat|grep -A 2 'nfs v4 operations'
Server nfs v4 operations:
op0-unused op1-unused op2-future access close commit
0 0% 0 0% 0 0% 10 4% 1 0% 1 0%
root@debianvboxtest:~# echo 'hello' >/mnt/test1056
root@debianvboxtest:~# nfsstat|grep -A 2 'nfs v4 operations'
Server nfs v4 operations:
op0-unused op1-unused op2-future access close commit
0 0% 0 0% 0 0% 11 4% 2 0% 2 0%
现在射频功能函数库,我读到过这样的文章:
COMMIT 操作在操作和语义上类似于 POSIX fsync(2) 系统调用,后者将文件的状态与磁盘同步(文件数据和元数据被刷新到磁盘或稳定存储)。 COMMIT 为客户端执行相同的操作,将服务器上任何未同步的数据和元数据刷新到服务器的磁盘或指定文件的稳定存储中。
我不明白客户端为什么要提交。我不认为“echo”shell 内置命令会运行fsync
;如果echo
写入本地文件,然后机器停机,则文件可能会丢失。相反,NFS 客户端似乎在完成时发送了 COMMIT echo
。为什么?
我不愿意使用async
NFS 服务器选项,因为它显然会忽略 COMMIT。我觉得好像我有一个本地文件系统,我必须在关闭时同步每个文件和fsync
完全忽略之间做出选择。我理解错了什么?
答案1
因为这就是 NFS 的工作方式,而且由于它是一种同步协议,因此它应该就是这样工作的。您需要确保导出的文件系统由具有 NVRAM/BBWC 保护的 LUN 支持,并正确处理 fsync() - 即忽略它,并屏蔽 SCSI FUA 标志和 SCSI_CACHE_SYNCHRONIZE 命令。此外,如果文件系统由 BBWC/NVRAM 支持,请确保它没有启用任何屏障。
这样,NFS 保持其同步语义,相当于每次写入后运行 fsync(),但您可以获得异步运行的性能。