如何在检查新创建的文件时强制刷新NFS缓存?

17
当在Linux NFS共享挂载上创建文件时,客户端可以是Linux或Mac机器。文件的存在或不存在是接下来要做什么的关键,但检查并不总是返回正确的结果。
例如,我正在perl中做这个操作,但仍然不能很好地工作,特别是在Mac机器上。
write_key_file();  # write a file that must be checked before proceeding

以下检查在文件存在时无法始终返回true

问题 - 在NFS系统中,此Perl命令未返回正确的状态:

if( -e $file){}

听到一个没有用的解决方案:

 sleep(5);   # wait 5 seconds
 system("ls -ltr"); # force to cache?
 if(-e $file){}

我不打算像这样检查每个文件,但有一些关键位置需要获取正确的文件状态。

我们有更好的方法来强制刷新特定目录中特定文件的nfs缓存吗?谢谢。

我不确定这是否是一个XY问题,但有一些最薄弱的点都可以成为解决方案。

 

A -- NFS客户端设置

如果此阶段有解决方案,那就太好了!

 

B -- 写入函数的退出代码或返回代码

$exit_code = write_key_file();

它的问题在于,不是所有的写入都在代码块的范围内。这只解决了部分问题。

C -- 禁用 NFS 缓存以进行文件检查的特定文件或目录

我需要确保这是否可行以及如何操作?如果不行,原因是什么?

我对所有可能的解决方案开放,没有解决方案或其他可能性。


2
这是一件不好的事情。你实际上想要达到什么目的?很可能有更好的方法。NFS通过设计进行缓存以提高效率。非缓存文件系统IO也可以完成,但比你想象的要慢得多。通常,答案是-尝试用不同的方式来做。 - Sobrique
2
这里有一个更直接的方法。 - ThisSuitIsBlackNot
1
我的观点是,这可能是一个XY问题。最好通过退一步并看看您试图实现什么来解决问题。 - Sobrique
2
如果调用成功,则可以使用sysopenO_RDWR|O_CREAT|O_EXCL强制刷新NFS缓存 - 如果文件不存在,则调用成功(但并非所有的NFS实现都正确处理O_EXCL)。我在Python中使用了这种技术(我不会Perl)。请参见我的回答http://stackoverflow.com/questions/29979624/can-i-prevent-a-script-from-launching-twice-using-open2-with-o-creat-and-flock/29986073#29986073。 - Dan Cornilescu
5
也许这值得一试:http://unix.stackexchange.com/a/207383。他在父目录上执行`opendir/closedir`操作。 - PerlDuck
显示剩余5条评论
1个回答

20

这个解决方案属于B类别:写入函数的退出码或返回码

...只有open()fopen()需要保证它们获取一个特定文件的一致句柄进行读写。不要求stat等函数检索新属性。因此,出于接近打开缓存一致性的考虑,仅将open()fopen()视为“打开事件”,在此事件中需要立即从服务器获取新属性[1]


以下解决方案属于A类别:NFS客户端设置
即,如果您不希望缓存的文件/目录条目被提供给客户端,请禁用缓存。

设置共享缓存

如果NFS挂载中的文件(其存在正在检查)是由同一客户端上的另一个应用程序创建的(可能使用指向相同NFS导出的另一个挂载点),则可以考虑在客户端上使用单个共享NFS缓存。

使用sharecache选项在客户端上设置NFS挂载。

该选项确定并发挂载相同导出时,客户端的数据缓存和属性缓存如何共享。使用相同的缓存可减少客户端的内存需求,并在通过不同的挂载点访问相同远程文件时向应用程序呈现相同的文件内容。


设置没有缓存的NFS挂载

禁用属性缓存。

使用noac选项在客户端上挂载NFS共享。

或者,禁用提供缓存的目录属性。

使用 acdirmin=0,acdirmax=0 将缓存超时设置为 0 (有效地禁用缓存)。


设置忽略查找缓存的 NFS 挂载

使用 lookupcache=positivelookupcache=none

(可用选项: all, positivenone)

尝试通过 NFS 挂载访问目录条目时,
如果所请求的目录条目存在于服务器上,则结果被称为 positive
如果所请求的目录条目不存在于服务器上,则结果被称为 negative

如果未指定 lookupcache 选项,或者指定了 all,则客户端假设这两种类型的目录缓存条目都是有效的,直到它们的父目录的缓存属性过期。

如果指定了 pospositive,则客户端假定正条目在其父目录的缓存属性过期之前都是有效的,但总是在应用程序使用它们之前重新验证负缓存项。

如果指定了 none,则客户端在应用程序使用它们之前重新验证这两种类型的目录缓存条目。这允许快速检测其他客户端创建或删除的文件,但会影响应用程序和服务器性能。


参考资料:
1. Linux NFS 客户端中的 Close-To-Open 缓存一致性
2. NFS - 如何通过程序检测远程创建的文件?
3. NFS 缓存:当服务器上的文件被修改时,客户端上的文件内容未更新
4. NFS手册页面,特别是"数据和元数据一致性"部分。


答案对我来说已经足够好了,我只会检查写入函数的退出代码。如果退出代码超出范围,我将保持现状,等待系统更新。谢谢。 - Gang
1
使用“noac”选项对我有用。然而,它不能添加到“remount”选项中。但是卸载和重新挂载当然可以解决问题。 - Marcell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接