NFS 服务器(它是某种 NAS 设备,我不知道是什么品牌,也不知道它是如何配置的)有一个文件系统导出并安装在 Linux 客户端上。服务器和客户端都位于同一个本地网络上。远程文件系统的布局如下:
/nfs/server/mount/data1/
client_uuid_1/
data_20170101.gz
data_20170102.gz
...
client_uuid_2/
data_20170101.gz
data_20170102.gz
...
...
data2/
client_uuid_3/
data_20170101.gz
data_20170102.gz
...
...
总共有 40,000 个 client_uuid_N 目录和 300,000 个数据文件。我注意到,一个必须扫描所有目录以查找新数据文件的脚本在执行 glob 操作时非常慢,因此我进一步调查并发现了这个奇怪的现象:
重新安装文件系统后,我第一次运行find /nfs/server/mount/data[12] -name data_*.gz > /dev/null
它大约需要五分钟。这已经非常慢了,表明存在某种问题,但情况变得更奇怪了。
这第二我运行该命令时需要时间是原来的四倍——差不多二十分钟。这与我的预期完全相反。
为什么会发生这种情况?
答案1
该find
命令扫描目录中的条目并获取文件属性以发现子目录并循环扫描它们。find
首次运行时,nfs 客户端将发出 READDIR 操作,除了获取目录列表外,还会询问文件属性。这非常高效,因为您只有几个 nfs 请求通过网络传输。第二次运行时,由于目录未更改,因此使用缓存列表。但是,客户端会检查每个文件的文件属性更改,这会增加总执行时间。从技术上讲,文件系统对象类型无法更改(文件永远不会成为目录),但 nfs 客户端不知道应用程序在调用时实际需要哪些属性stat
,find
命令查询所有文件属性时会使用它。
这听起来有悖常理,但如果你删除文件系统缓存(echo 3 > /proc/sys/vm/drop_cache
在 Linux 上),那么在第二次运行时你也会获得更好的性能。
有一个讨论如果您想更深入地了解 Linux 实现的技术细节,请参阅 Linux nfs 邮件列表。