问题
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
- 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
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.
Is java.nio.FileLock really intended for this kind of use? Or should I be looking at something else?
回答1:
Here is what I ended up doing. For every file named "XXX", I use a zero length lock file named "XXX#LOCK"
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.
I unlock the lockfile
The code for locking:
File lockFile = new File(target.getParent(), target.getName() + "#LOCK");
lockAccessFile = new RandomAccessFile(lockFile, "rw");
FileChannel lockChannel = lockAccessFile.getChannel();
lock = lockChannel.lock();
code for unlocking:
if (lock != null) {
lock.release();
lock = null;
}
if (lockAccessFile != null) {
lockAccessFile.close();
lockAccessFile = null;
}
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.
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.
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.
来源:https://stackoverflow.com/questions/38526966/how-best-to-file-lock-in-java-cluster