最近同事發來一個bug,如圖所示:
以前跑的一直是沒問題,但不知爲何突然會報這個錯。
google一下搜到:http://www.gossamer-threads.com/lists/lucene/java-user/100965
其中ian.lea at gmail 提出幾點:
1、文件路徑問題。
2、使用SimpleFSLockFactory而不是默認的native class類。
3、使用lucene的最新版本。
由於無法遠程調試這個問題還得等到下週同事過去才能去處理。
趁着這機會又去了解了一下Lucene中的Lock。
圖1-lock實現類
圖2-LockFactory實現類
SingleInstanceLockFactory:用一個lock對象來表示鎖定,默認用於RAMDirectory。
Implements LockFactory
for a single in-process instance, meaning all locking will take place through this one instance. Only use this LockFactory
when you are certain all IndexReaders and IndexWriters for a given index are running against a single shared in-process Directory instance. This is currently the default locking for RAMDirectory.
NoLockFactory:就是不採用lock。
Use this LockFactory
to disable locking entirely. Only one instance of this lock is created. You should call getNoLockFactory()
to get the instance.
文件鎖有兩種NativeFSLockFactory和SimpleFSLockFactory。
SimpleFSLockFactory:鎖的一種簡單實現。
Implements LockFactory
using File.createNewFile()
.
NOTE: the javadocs for File.createNewFile
contain a vague yet spooky warning about not using the API for file locking. This warning was added due to this bug, and in fact the only known problem with using this API for locking is that the Lucene write lock may not be released when the JVM exits abnormally.
When this happens, a LockObtainFailedException
is hit when trying to create a writer, in which case you need to explicitly clear the lock file first. You can either manually remove the file, or use the IndexWriter.unlock(Directory)
API. But, first be certain that no writer is in fact writing to the index otherwise you can easily corrupt your index.
NativeFSLockFactory(Lucene3中開始設爲默認鎖):是調用OS本身的鎖定機制,這又是來自NIO的支持(private FileLock lock;lock = channel.tryLock();)。相比缺省的SimpleFSLockFactory,這種鎖纔是真正的鎖。在File.createNewFile()的javadoc中,明確指出用這個方法來做鎖是不可靠的。但是不是所有的文件系統都支持鎖機制的,有些文件系統要經過配置才能支持(註釋裏提到NFS)。沒辦法的情況下,只好用SimpleFSLockFactory來湊個數。
Implements LockFactory
using native OS file locks. Note that because this LockFactory relies on java.nio.* APIs for locking, any problems with those APIs will cause locking to fail. Specifically, on certain NFS environments the java.nio.* locks will fail (the lock can incorrectly be double acquired) whereas SimpleFSLockFactory
worked perfectly in those same environments. For NFS based access to an index, it's recommended that you try SimpleFSLockFactory
first and work around the one limitation that a lock file could be left when the JVM exits abnormally.
The primary benefit of NativeFSLockFactory
is that lock files will be properly removed (by the OS) if the JVM has an abnormal exit.
Note that, unlike SimpleFSLockFactory
, the existence of leftover lock files in the filesystem on exiting the JVM is fine because the OS will free the locks held against these files even though the files still remain.
在API中還有這麼一句話:If you suspect that this or any other LockFactory is not working properly in your environment, you can easily test it by using VerifyingLockFactory
, LockVerifyServer
and LockStressTest
.
當你猜測在你的環境中某個鎖文件不能正常工作,則可以通過 VerifyingLockFactory
, LockVerifyServer
和LockStressTest
很容易地測試出來。
VerifyingLockFactory
A LockFactory
that wraps another LockFactory
and verifies that each lock obtain/release is "correct" (never results in two processes holding the lock at the same time). It does this by contacting an external server (LockVerifyServer
) to assert that at most one process holds the lock at a time. To use this, you should also run LockVerifyServer
on the host & port matching what you pass to the constructor.
LockVerifyServer
Simple standalone server that must be running when you use VerifyingLockFactory
. This server simply verifies at most one process holds the lock at a time.
Run without any args to see usage.
LockStressTest
Simple standalone tool that forever acquires & releases a lock using a specific LockFactory. Run without any args to see usage.