My Application有两个组件在两个不同的JVM进程中运行。
1)Spring Boot RestAPI
2)Spring Boot批处理(API提交的处理作业)
我使用" Hibernate Search"使用Spring,这两个组件都需要更新搜索索引。
然而,似乎锁是由JVM进程获取的,它首先启动,当另一个组件尝试更新索引时,它会抛出异常。
如何让这两个JVM进程更新索引而不会出现此锁定问题?
2017-05-22 02:33:56.795 ERROR 14701 --- [del.FeatureMeta] o.h.s.exception.impl.LogErrorHandler : HSEARCH000058: Exception occurred org.apache.lucene.store.LockObtainFailedException: Lock held by another program: /home/bisuser/cdna-meta-index/default/com.company.dsd.cdna.repository.model.FeatureMeta/write.lock
Primary Failure:
Entity com.company.dsd.cdna.repository.model.FeatureMeta Id 169 Work Type org.hibernate.search.backend.UpdateLuceneWork
org.apache.lucene.store.LockObtainFailedException: Lock held by another program: /home/bisuser/cdna-meta-index/default/com.company.dsd.cdna.repository.model.FeatureMeta/write.lock
at org.apache.lucene.store.NativeFSLockFactory.obtainFSLock(NativeFSLockFactory.java:118) ~[lucene-core-5.5.4.jar!/:5.5.4 31012120ebbd93744753eb37f1dbc5e654628291 - jpountz - 2017-02-08 19:08:03]
at org.apache.lucene.store.FSLockFactory.obtainLock(FSLockFactory.java:41) ~[lucene-core-5.5.4.jar!/:5.5.4 31012120ebbd93744753eb37f1dbc5e654628291 - jpountz - 2017-02-08 19:08:03]
at org.apache.lucene.store.BaseDirectory.obtainLock(BaseDirectory.java:45) ~[lucene-core-5.5.4.jar!/:5.5.4 31012120ebbd93744753eb37f1dbc5e654628291 - jpountz - 2017-02-08 19:08:03]
at org.apache.lucene.index.IndexWriter.<init>(IndexWriter.java:776) ~[lucene-core-5.5.4.jar!/:5.5.4 31012120ebbd93744753eb37f1dbc5e654628291 - jpountz - 2017-02-08 19:08:03]
at org.hibernate.search.backend.impl.lucene.IndexWriterHolder.createNewIndexWriter(IndexWriterHolder.java:126) ~[hibernate-search-engine-5.6.1.Final.jar!/:5.6.1.Final]
at org.hibernate.search.backend.impl.lucene.IndexWriterHolder.getIndexWriter(IndexWriterHolder.java:92) ~[hibernate-search-engine-5.6.1.Final.jar!/:5.6.1.Final]
at org.hibernate.search.backend.impl.lucene.AbstractWorkspaceImpl.getIndexWriter(AbstractWorkspaceImpl.java:117) ~[hibernate-search-engine-5.6.1.Final.jar!/:5.6.1.Final]
at org.hibernate.search.backend.impl.lucene.AbstractWorkspaceImpl.getIndexWriterDelegate(AbstractWorkspaceImpl.java:203) ~[hibernate-search-engine-5.6.1.Final.jar!/:5.6.1.Final]
at org.hibernate.search.backend.impl.lucene.LuceneBackendQueueTask.applyUpdates(LuceneBackendQueueTask.java:81) [hibernate-search-engine-5.6.1.Final.jar!/:5.6.1.Final]
at org.hibernate.search.backend.impl.lucene.LuceneBackendQueueTask.run(LuceneBackendQueueTask.java:46) [hibernate-search-engine-5.6.1.Final.jar!/:5.6.1.Final]
at org.hibernate.search.backend.impl.lucene.SyncWorkProcessor$Consumer.applyChangesets(SyncWorkProcessor.java:165) [hibernate-search-engine-5.6.1.Final.jar!/:5.6.1.Final]
at org.hibernate.search.backend.impl.lucene.SyncWorkProcessor$Consumer.run(SyncWorkProcessor.java:151) [hibernate-search-engine-5.6.1.Final.jar!/:5.6.1.Final]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_112]
答案 0 :(得分:1)
为了让Lucene提供不错的性能,必须使用独家锁。您可以禁用它,但需要付费。
原因是仍然会有锁定机制,但锁只会在很短的时间内使用。这意味着索引不会并行写入,并且其他JVM进程可能会等待尝试获取锁(可能性能不佳)。更糟糕的是,这些获取锁定的尝试可能会失败:它们可能会超时。鉴于锁定队列不公平(要求锁定的最后一个JVM进程可能是第一个得到它),并且超时处理相当粗糙(一次尝试,然后是另一个类似2s之后,然后超时)这里失败的风险很高。
因此,如果您确定不会对锁进行任何强烈争用(例如,大规模索引作业仅在夜间或周末运行),则禁用独占锁定可能是一种选择;否则,由于锁定超时,您可能会遇到严重的滞后和/或失败。
请参阅the documentation中的hibernate.search.[default|<indexname>].exclusive_index_use
。
可替换地: