从通过 NFS 线程访问的文件中提取第一行是否安全?

从通过 NFS 线程访问的文件中提取第一行是否安全?

如果我通过 NFS 在多个服务器上挂载一个目录,每个服务器都运行一个读取和删除该目录中特定文件的第一行的进程,是否可以以某种方式保证没有行被读取两次或删除而不被提取?

显然,我可以创建某种互斥体,只允许一个进程对 NFS 安装的文件进行操作,但是是否有一种构建方法可以实现这一目标?

答案1

如果我通过 NFS 在多个服务器上挂载一个目录,每个服务器都运行一个读取和删除该目录中特定文件的第一行的进程,是否可以以某种方式保证没有行被读取两次或删除而不被提取?

您可以保证该行不会被删除,除非很容易提取:只是不要这样做。不要让您的处理删除该行,除非它已经“提取”了它,无论是什么。

你能保证一行只被处理一次吗?事实并非如此——NFS 中存在各种各样的计时漏洞。数据和元数据都缓存在每个客户端上,即使禁用所有缓存,网络数据传输也会出现明显的时间延迟。一台服务器上的进程可能无法“看到”发生的事情,直到为时已晚。

但您似乎错过了一个更大的问题:删除文件的第一行需要重写文件的整个其余部分。由于您似乎正在尝试将此文件用作某种 FIFO,因此我还假设您有其他进程将行附加到文件末尾。当多个客户端在删除第一行后重写整个文件时,您认为这种方法的效果如何?甚至如果您可以让客户端正确同步,您必须将任何写入进程添加到同步集群中。

这几乎就是您需要创建的 - 一个软件集群全部共享一个需要完全锁定才能更新其内容的文件 - 无论是重写整个文件而不包含第一行,还是附加到文件末尾。

能做到可靠吗?当然可以,但不能仅使用 NFS。

如果您正在考虑使用文件作为 FIFO,您可能会做得更好,只需将每一行放入单独的文件中,然后使用rename()将文件从公共目录移动到同一 NFS 安装的文件系统上的客户端特定目录。每个客户端都有自己的目录,如果工作rename()正常,它就会知道它已成功“声明”该文件,如果失败,它将假定另一个客户端“声明”该文件。

希望您的 NFS 实现足够强大,能够rename()正确处理 NFS 服务器上的冲突尝试,其中只有一个客户端工作并成功返回,rename()而所有其他客户端都会失败 - 不会锁定 NFS 服务器或使内核崩溃。

相关内容