Java BTRFS上未关闭的文件和旧版本重新出现

Java BTRFS上未关闭的文件和旧版本重新出现,java,java-8,centos7,btrfs,Java,Java 8,Centos7,Btrfs,在对BTRFS手册页进行了大量测试和挖掘之后,我需要一些Linux/BTRFS人员的帮助 我有一个java应用程序,它使用java MappedByteBuffer实用程序将数据文件写入磁盘。这是应用程序在写入磁盘时使用约16000字节的字节缓冲区。当一个新文件被写入时,它会创建一个缓冲区大小的临时文件,并且由于mem映射文件的java实现,代码不会显式关闭该文件。相反,我们称Linux的drop_缓存为强制将未使用的内存映射刷新到磁盘 在EXT4上,这些文件会自动关闭,并正确调整文件大小 在

在对BTRFS手册页进行了大量测试和挖掘之后,我需要一些Linux/BTRFS人员的帮助

我有一个java应用程序,它使用java MappedByteBuffer实用程序将数据文件写入磁盘。这是应用程序在写入磁盘时使用约16000字节的字节缓冲区。当一个新文件被写入时,它会创建一个缓冲区大小的临时文件,并且由于mem映射文件的java实现,代码不会显式关闭该文件。相反,我们称Linux的drop_缓存为强制将未使用的内存映射刷新到磁盘

  • 在EXT4上,这些文件会自动关闭,并正确调整文件大小
  • 在BTRFS上,这些文件保留约16000字节,并且缺少一些数据(可能是分页问题)
  • 在BTRFS上,当我删除这些文件,软件重新运行并再次创建这些文件时,每次都会出现相同的问题,修改日期是从最初创建文件时开始的
服务器信息: 我们运行的是最新的centos 7.2,并且有最新的补丁

  • OS Centos 7 x64(内核3.10.0-514.10.2.el7.x86_64)
  • btrfs程序v4.4.1
  • Java 1.8.0_111
执行的测试

  • 我们有一个在Ext4上运行的副本服务器,但这个问题没有发生

  • 我们目前正在使用COW和压缩,所以我尝试禁用它们,重新启动、删除旧数据并重新启动软件。问题仍然存在

  • 我还尝试过禁用空间缓存、恢复,并尝试使用flushoncommit设置commit=5…这也无助于非关闭文件/错误的修改日期
由于mem映射文件的java实现,代码没有显式关闭该文件

这没有多大意义。文件支持的内存映射不要求其文件描述符保持打开状态。因此,您完全可以在创建映射缓冲区后关闭文件

相反,我们称Linux的drop_缓存为强制将未使用的内存映射刷新到磁盘

这是巨大的杀伤力

  • 用于将更改同步到磁盘
  • 重命名临时文件
  • fsync重命名后为确保崩溃持久性所需的目录(请参阅下面的参考资料)



    是否保证我们可以以
    ByteChannel
    的身份打开目录?@Holger文档还没有保证,但unix语义需要它,当该功能在JDK9开发周期中被删除时,会有投诉,因此删除被恢复,因此很可能在将来。见@the8472谢谢您的详细回复!强制选项是我们考虑过的,但由于它的同步性质,我们决定不实施它。我完全同意频繁的drop_缓存是过度的,我们正在努力寻找更好的解决方案。我想我的主要问题是Centos 7上的BTRFS,BTRFS处理内存映射文件与ext4不同,还是这是一个bug?(问题:文件未正确关闭,重新创建文件时使用了旧的修改日期)
    try(FileChannel dir = FileChannel.open(Paths.get("/path/directory"), StandardOpenOptions.READ)) {
      dir.force(true);
    }