我有一个流程:
- 写入一个新的‘.tmp’文件。
- 使用
rename()
系统调用来替换现有文件。 - 正在从远程 NFS 客户端访问该文件。
我们这样做,因为我们想要原子文件更新,并且rename()
spec 说:
如果 newpath 已经存在,它将被自动替换,这样尝试访问 newpath 的另一个进程就不会发现它丢失了。但是,可能会有一个窗口,其中 oldpath 和 newpath 都引用被重命名的文件。
我们依赖于这种行为。
但这里有一个问题——就在最近,自从迁移到新的 NetApp(集群模式,从 7 模式)以来——我们遇到了一个偶尔会失败的过程ENOENT
——没有这样的文件或目录。
我所说的“非常偶尔”是指过去几周内出现 4 到 5 次,大约每 5 分钟发生一次。
我正在与供应商一起调查这是否是他们的 NFS 服务器的一个错误。
但我实际上想弄清楚的是,这种原子性保证是否真的适用于 NFS。有人能帮我澄清一下原子性保证是否适用rename()
于多客户端 NFS 场景吗?我实际上不确定这个功能是否一直在起作用,但从未被保证首先。
从:RFC1813
过程 RENAME 将目录 from.dir 中由 from.name 标识的文件重命名为目录 to.dir 中的 to.name。此操作对于客户端而言必须是原子的。
如果相关的话,我们让 SL 6.5 客户端访问 ONTAP-CDOT 8.3 上的 NFS 数据存储。
答案1
避免 NFS 中的竞争条件
这始终是一个有趣的挑战,我知道的唯一解决方法是无需重写应用程序,使用选项安装共享sync
并更改要使用的 NFS 服务器no_wdelay
。我不记得如何在 NetApp 中设置 no_wdelay。
这种方法的缺点是,如果您有大量同时写入此共享的内容,它们的速度将呈指数级下降。您可能想问 NetApp 如何在共享上设置 no_wdelay,或者直接向他们描述问题。他们可能有更好的想法。我至少 8 年没有接触过 NetApp 了。