问题描述
我有一组在JBoss上运行的服务器。我需要以安全的方式更新文件。具体来说,我需要
I have a cluster of servers running on JBoss. I need to update a file in a safe manner. To be specific, I need to
- 锁定文件A-以安全的方式阻止文件A的锁定,以便JVM突然死了,没有悬挂的锁。 30秒的超时时间就可以了。
- 读取文件A
- 更改内容
- 编写文件文件更改为临时名称A.tmp
- 删除原始文件A
- 将A.tmp重命名为适当的名称A
- 解锁文件A
- lock a file A -- blocking if it is already locked, in a safe manner so that if the JVM was to die suddenly there would no dangling locks. A 30 second timeout would be fine.
- read the file A
- change the contents
- write the file to a temp name A.tmp
- delete the original file A
- rename the A.tmp to the proper name A
- unlock the file A
当我查看java.nio.FileLock时,它似乎与InputStream。我真的只需要锁定一个抽象名称。我不需要锁定文件的一部分。如果可以的话,我可以为此创建一个锁定文件(与数据文件分开)。但是,我的问题的重点是我需要在读取之前获取锁,然后在更新文件后释放锁。请注意,我以某种方式更新文件,以确保文件系统上永远不会有部分写入的文件。我需要写入整个文件,然后在写入后对其进行重命名,以确保拥有该名称的任何文件都具有完整的内容集,并且如果在写入过程中进程死了,则会留下一个临时文件,可以轻松清除该文件
When I look at java.nio.FileLock, it seems to be associated with an InputStream. I really just need to lock an abstract name. I don't need to lock a portion of a file. I could create a lock file for this (separate from the data file) if that is the best choice. However the main point of my problem is that I need to get the lock BEFORE I read, and then release the lock after I update the file. Note that I update the file in a manner to assure that I never have a partially written file on the file system. I need to write the whole file, and then rename it after it is written, to assure that whatever file holds that name has a complete set of contents, and if the process dies during writing it leaves behind a temp file which can easily be cleaned up later.
java.nio.FileLock是否真的打算用于这种用途?还是我应该看看别的东西?
Is java.nio.FileLock really intended for this kind of use? Or should I be looking at something else?
推荐答案
这就是我最后要做的事情。对于每个名为 XXX的文件,我都使用一个名为 XXX#LOCK的零长度锁定文件
Here is what I ended up doing. For every file named "XXX", I use a zero length lock file named "XXX#LOCK"
-
我将其锁定为用RandomAccessFile更新。
I lock this for update with an RandomAccessFile.
在锁定此锁定文件的同时,我操纵了有问题的实际文件:读取原始文件,流式传输到临时文件,删除原始文件并重命名临时文件等。
While this lock file is locked, I manipulate the actual files in question: reading original file, streaming to a temp file, deleting the original, and renaming the temp file, etc.
我解锁了锁定文件
锁定代码:
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
是成员变量。
I wrap this together in a class that makes the locking and unlocking together with the reading or writing of the original file. As you can see, lock
and lockAccessFile
are member variables.
我从未真正将任何内容写入锁定文件,但是它们存在于文件夹中。由于我只有很少的文件可以通过这种方式进行管理(其中有6个),因此我只是将LOCK文件保留在其中,尽管它们丑陋但无害,而且开销很大。
I never actually write anything to the lock file, but they exist in the folder. Since I have a small number of files to manage in this way (6 of them), I just leave the LOCK files in there as ugly, but harmless, overhead.
这在跨多主机群集的代码中起作用,因为我的代码是操作这些文件的唯一方法。最大的问题是,如果其他一些代码在不了解此约定的情况下开始处理文件,则会引起问题。我还没有找到任何证据表明有一种标准方法可以解决此问题,该方法将由操作系统强制实施,并同时由Java支持。如果您有任何了解,请告诉我。
This works within my code across the multi-host cluster because my code is the only thing manipulating those files. The biggest problem is that if some other code started manipulating the files without knowing this convention, it would cause problems. i have not found any evidence that there is a standard way to handle this problem that would be enforced by the OS and at the same time supported by Java. If you know of any, let me know.
这篇关于如何在Java集群中最好地进行文件锁定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!