如何最好地在Java集群中锁定文件

时间:2016-07-22 12:52:17

标签: java io cluster-computing

我在JBoss上运行了一组服务器。我需要以安全的方式更新文件。具体来说,我需要

  1. 锁定文件A - 如果它已经被锁定,则以安全的方式阻止,这样如果JVM突然死亡,就不会有悬空锁。 30秒的超时时间没问题。
  2. 阅读文件A
  3. 更改内容
  4. 将文件写入临时名称A.tmp
  5. 删除原始文件A
  6. 将A.tmp重命名为正确的名称A
  7. 解锁文件A
  8. 当我查看java.nio.FileLock时,它似乎与InputStream相关联。我真的只需要锁定一个抽象名称。我不需要锁定文件的一部分。如果这是最佳选择,我可以为此创建一个锁定文件(与数据文件分开)。然而,我的问题的主要问题是我需要在读取之前获取锁定,然后在更新文件后释放锁定。请注意,我更新文件的方式是为了确保文件系统上没有部分写入的文件。我需要编写整个文件,然后在编写后重命名它,以确保任何文件保存该名称都有一整套内容,如果进程在写入过程中死亡,则会留下一个可以轻松清理的临时文件以后。

    java.nio.FileLock真的是用于这种用途吗?或者我应该看别的东西?

1 个答案:

答案 0 :(得分:0)

这是我最终做的事情。对于名为“XXX”的每个文件,我使用名为“XXX#LOCK”的零长度锁定文件

  1. 我使用RandomAccessFile将其锁定以进行更新。

  2. 当这个锁文件被锁定时,我操纵了有问题的实际文件:读取原始文件,流式传输到临时文件,删除原始文件,重命名临时文件等。

  3. 我解锁了锁文件

  4. 锁定代码:

        if (lock != null) {
            lock.release();
            lock = null;
        }
        if (lockAccessFile != null) {
            lockAccessFile.close();
            lockAccessFile = null;
        }
    

    解锁代码:

    lock

    我将它包装在一个类中,该类将锁定和解锁与原始文件的读取或写入一起进行。如您所见,lockAccessFile和{{1}}是成员变量。

    我实际上从未向锁文件写任何内容,但它们存在于文件夹中。由于我以这种方式管理少量文件(其中6个),我只是将LOCK文件留在那里,因为它是丑陋但无害的开销。

    这在我的代码中适用于多主机群集,因为我的代码是唯一操纵这些文件的东西。最大的问题是,如果其他一些代码在不知道此约定的情况下开始操作文件,则会导致问题。我没有找到任何证据表明有一种标准的方法来处理这个问题,这个问题将由操作系统强制执行,同时由Java支持。如果你知道,请告诉我。