【问题标题】:Filesystem lock in JavaJava中的文件系统锁
【发布时间】:2014-04-28 23:08:16
【问题描述】:

从文件中读取行并处理它们时,我在某些代码中使用了文件系统锁。这是因为我的架构有不止一个应用服务器;我只希望单个服务器处理每一行以避免数据重复。

我在辅助方法中创建了一个 DTO。该对象填充了锁定详细信息,该详细信息可以由辅助方法返回,并且可以随后查询以查看锁定是否成功。如果是这样,就可以处理文件中的行。

通常,如果两台服务器同时尝试处理文件中的行,则其中一台服务器会抛出异常,因为该文件已被另一台服务器锁定。如果发生这种情况,我的代码会捕获异常并移至文件的下一行。

锁实现如下:

String filename = <Unique identifier of record being processed>;
File lockfile = new File(System.getProperty("java.io.tmpdir"), filename);
RandomAccessFile randomAccessfile = new RandomAccessFile(lockfile, "rw");
FileChannel fileChannel = randomAccessfile.getChannel();

FileLockDTO fileLockDTO = new FileLockDTO();
fileLockDTO.setLockedfile(lockfile);
fileLockDTO.setRandomAccessfile(randomAccessfile);
fileLockDTO.setFileLock(fileChannel.tryLock()); 

在绝大多数情况下,代码运行良好。然而,在极少数情况下,会出现重复记录,这表明存在多个应用程序服务器似乎可以在完全相同的时刻创建锁的边缘情况。

我仔细查看了代码并尝试了许多测试,但无法确定这是如何发生的。只是想知道是否有人有任何想法?

提前感谢您的帮助。

【问题讨论】:

  • 我使用的是 Java 1.7 版。
  • 那你想试试Files.createFile(pathHere).
  • 让应用服务器从文件中读取行似乎不太可能成功。你需要一个真正的排队系统;您可以使用 AMQ、ZMQ、MongoDB 或 ...
  • 您的锁定文件是纯粹用于锁定的辅助文件吗?另外,您是否在任何其他代码中打开锁定文件?
  • @jtahlborn 这些文件纯粹用于在这种情况下锁定,不用于其他任何地方。

标签: java io nio


【解决方案1】:

来自FileLockjavadocs:

锁是否真正阻止另一个程序访问锁定区域的内容取决于系统,因此未指定。某些系统的本机文件锁定功能只是建议性的,这意味着程序必须协同遵守已知的锁定协议以保证数据完整性。

来自FileChannel.tryLock() javadocs:(重点是我的)一个OverlappingFileLockException被抛出

如果一个与请求区域重叠的锁已被此 Java 虚拟机持有,或者如果 另一个线程已在此方法中被阻塞并试图锁定一个重叠区域

以下是您的应用的简单失败场景:

  1. 服务器 A 查询资源 1 上是否存在锁 => 返回 false
  2. 服务器 B 查询资源 1 上是否存在锁 => 返回 false
  3. 服务器 A 在上面的代码 sn-p 中运行第 1-4 行并成功
  4. 服务器 B 在上面的代码 sn-p 中运行第 1-4 行并成功(什么会阻止它?)
  5. 服务器 A 创建 DTO
  6. 服务器 B 创建 DTO(取决于操作系统,对 tryLock() 的调用可能不会停止任何事情)
  7. 服务器 A 处理“锁定”记录
  8. 服务器 B 处理“锁定”记录

【讨论】:

    【解决方案2】:

    您必须依赖 FileLockDTO.setFileLock() 或您拥有它的任何地方的空检查,如果您确实拥有它的话。这一切对我来说似乎太复杂了。我只会锁定您正在阅读的实际文件的实际行,而不是引入这些辅助锁定文件。然后,如果您遇到现有的锁,您知道跳过该行。或者使用一种数据结构,该数据结构能够仅交付每行一次并消除整个问题,例如某种 MQ 或数据库。

    编辑反对者和/或文件锁不能跨 JVM 或进程工作的理论的拥护者需要阅读文档。

    【讨论】:

    • @Asaph 不幸的是,Javadoc 不同意你的观点:“这个文件锁定 API 旨在直接映射到底层操作系统的本机锁定设施。因此,文件上的锁定应该对所有有权访问该文件的程序可见,无论这些程序是用什么语言编写的。"
    • 我正在阅读文档并引用和链接到它们。抛出OverlappingFileLockException“如果此 Java 虚拟机已持有与请求区域重叠的锁,或者如果另一个线程已在此方法中阻塞并试图锁定同一文件的重叠区域”--@ 987654321@
    • @Asaph 这绝不支持您的论点。它也不与我引用的部分相矛盾。你正抓着稻草。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-04
    • 2015-06-18
    • 2023-04-06
    • 2023-04-07
    • 1970-01-01
    • 2011-03-12
    • 1970-01-01
    相关资源
    最近更新 更多