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

如何在Java集群中最好地锁定文件,java,io,cluster-computing,Java,Io,Cluster Computing,我有一个运行在JBoss上的服务器集群。我需要以安全的方式更新文件。具体来说,我需要 锁定一个文件——如果它已经被锁定,则以安全的方式阻止它,这样,如果JVM突然死亡,就不会有悬空的锁。30秒的超时时间就可以了 读取文件A 更改内容 将文件写入临时名称a.tmp 删除原始文件A 将A.tmp重命名为正确的名称A 解锁文件A 当我查看java.nio.FileLock时,它似乎与InputStream关联。我真的需要锁定一个抽象名称。我不需要锁定文件的一部分。如果这是最好的选择,我可以为此创建一个

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

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


    java.nio.FileLock真的适合这种用途吗?还是我应该看看别的东西?

    以下是我最后做的事情。对于每个名为“XXX”的文件,我使用一个名为“XXX#lock”的零长度锁文件

  • 我用一个随机访问文件锁定此更新

  • 当这个锁定文件被锁定时,我会处理实际的文件:读取原始文件、流式传输到临时文件、删除原始文件和重命名临时文件,等等

  • 我打开锁文件

  • 锁定代码:

        File lockFile = new File(target.getParent(), target.getName() + "#LOCK");
        lockAccessFile = new RandomAccessFile(lockFile, "rw");
        FileChannel lockChannel = lockAccessFile.getChannel();
        lock = lockChannel.lock();
    
    解锁代码:

        if (lock != null) {
            lock.release();
            lock = null;
        }
        if (lockAccessFile != null) {
            lockAccessFile.close();
            lockAccessFile = null;
        }
    
    我将其封装在一个类中,该类可以在读取或写入原始文件的同时进行锁定和解锁。如您所见,
    lock
    lockAccessFile
    是成员变量

    我从未向锁定文件写入任何内容,但它们存在于文件夹中。因为我有一小部分文件要用这种方式管理(其中6个),所以我只是把锁文件放在那里,作为丑陋但无害的开销


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

    我认为您可以使用普通的旧数据库处理您的案例。并依赖于记录锁、事务超时和约束。若你们并没有数据库,你们可以试试ApacheZookeepertHanks,很好。这正是DB为您所做的。但是对于这段代码,保持低依赖性很重要,我只有6个文件要管理。它们的使用量很小,因此不需要大量的开销。锁定文件系统确实满足了这种情况下的需要。请在以下位置找到此系统的最新实现: