您可能遇到了 Unix 客户端缓存。O'Reilly NFS 书中有很多细节。
但简而言之:
当多台机器读取和写入同一个文件时,使用缓冲区缓存并允许异步线程集群多个缓冲区会带来一些问题。为了防止同一文件的多个读取器和写入器的文件不一致,NFS 制定了关闭时刷新策略:当文件关闭时,文件的所有部分填充的 NFS 数据缓冲区都将写入 NFS 服务器。
对于 NFS 版本 3 客户端,在稳定标志设置为关闭的情况下完成的任何写入都将通过提交操作强制到服务器的稳定存储上。
NFS 缓存一致性使用一种称为接近打开缓存一致性的方法——也就是说,您必须在服务器(和其他客户端)获得一致的最新文件视图之前关闭文件。您看到了这种方法的缺点,该方法旨在最大限度地减少服务器命中。
Java 很难避免缓存。open()
O_DIRECT
如果您使用的是 Linux,则需要设置文件标志;有关更多信息,请参阅此答案https://stackoverflow.com/a/16259319/5851520,但基本上它会禁用该文件的客户端操作系统缓存,尽管不是服务器的。
不幸的是,标准 JDK 没有公开O_DIRECT
. 如这里所讨论的:强制 JVM 在没有页面缓存的情况下执行所有 IO(例如 O_DIRECT) - 本质上,您自己使用 JNI 或使用不错的 3rd 方库。我听说过关于 JNA 的好消息:https ://github.com/java-native-access/jna ...
或者,如果您可以控制客户端挂载点,则可以sync
按照NFS 手册使用挂载选项。它说:
如果在挂载点上指定了同步选项,则任何将数据写入该挂载点上的文件的系统调用都会导致该数据在系统调用将控制权返回给用户空间之前刷新到服务器。这在客户端之间提供了更大的数据缓存一致性,但性能成本很高。
这可能是您正在寻找的。