LockObtainFailedException使用solr更新Lucene搜索索引

thr*_*ups 13 lucene solr

我已经google了很多.大多数问题都是由JVM崩溃后留下的锁引起的.这不是我的情况.

我有一个包含多个读者和作者的索引.我正在尝试进行批量索引更新(删除和添加 - 这就是lucene更新的方式).我正在使用solr的嵌入式服务器(org.apache.solr.client.solrj.embedded.EmbeddedSolrServer).其他编写者正在使用远程非流式服务器(org.apache.solr.client.solrj.impl.CommonsHttpSolrServer).

我启动了这个大规模的更新,它运行了一段时间,然后死了一个

引起:org.apache.lucene.store.LockObtainFailedException:Lock获取超时:NativeFSLock @/.../lucene-ff783c5d8800fd9722a95494d07d7e37-write.lock

我在solrconfig.xml中调整了锁定超时

<writeLockTimeout>20000</writeLockTimeout>
<commitLockTimeout>10000</commitLockTimeout>
Run Code Online (Sandbox Code Playgroud)

我即将开始阅读lucene代码来解决这个问题.任何帮助,所以我不必这样做会很棒!

编辑:我的所有更新都通过以下代码(Scala):

val req = new UpdateRequest
req.setAction(AbstractUpdateRequest.ACTION.COMMIT, false, false)
req.add(docs)

val rsp = req.process(solrServer)
Run Code Online (Sandbox Code Playgroud)

solrServer 是org.apache.solr.client.solrj.impl.CommonsHttpSolrServer,org.apache.solr.client.solrj.impl.StreamingUpdateSolrServer或org.apache.solr.client.solrj.embedded.EmbeddedSolrServer的实例.

另一个编辑:我停止使用EmbeddedSolrServer,现在可以使用了.我有两个单独的进程来更新solr搜索索引:

1)Servlet 2)命令行工具

命令行工具使用的是EmbeddedSolrServer,它最终会因LockObtainFailedException而崩溃.当我开始使用StreamingUpdateSolrServer时,问题就消失了.

我仍然有点困惑,EmbeddedSolrServer可以工作.有人可以解释一下吗.我认为它会对Servlet进程起到很好的作用,并且在另一个写入时它们会等待.

Xod*_*rap 13

我假设你做的事情如下:

writer1.writeSomeStuff();
writer2.writeSomeStuff();  // this one doesn't write
Run Code Online (Sandbox Code Playgroud)

这不起作用的原因是因为作者保持打开,除非你关闭它.因此writer1写入并保持锁定,即使在写完之后也是如此.(一旦一个writer2编写器获得一个锁,它就永远不会释放,直到它被销毁.)无法获得锁定,因为writer1仍然保持锁定,所以它会抛出一个LockObtainFailedException.

如果你想使用两个作家,你需要做类似的事情:

writer1.writeSomeStuff();
writer1.close();
writer2.open();
writer2.writeSomeStuff();
writer2.close();
Run Code Online (Sandbox Code Playgroud)

由于您一次只能打开一个作者,这几乎抵消了使用多个作者所带来的任何好处.(实际上打开和关闭它们实际上要糟糕得多,因为你将不断支付预热罚款.)

所以我怀疑的答案是你的根本问题是:不要使用多个作家.使用具有多个线程访问它的单个编写器(IndexWriter是线程安全的).如果您通过REST或其他HTTP API连接到Solr,则单个Solr编写器应该能够处理许多请求.

我不确定您的用例是什么,但另一个可能的答案是看Solr的管理多个索引的建议.特别是热插拔核心的能力可能是有意义的.


tro*_*ble 6

>> 但是你有多个Solr服务器写到同一个位置,对吗?

没有错.Solr正在使用Lucene库,并且在"Lucene in Action"*中声明,一次只能有一个进程/线程写入索引.这就是作家锁定的原因.

尝试编写的并发进程可能org.apache.lucene.store.LockObtainFailedException在实例化编写器时检查异常.

例如,您可以将实例化writer2在等待循环中的进程等待,直到活动写入过程完成并发出writer1.close();然后释放锁定并使Lucene索引可用于再次写入.或者,您可以同时写入多个Lucene索引(在不同位置),在进行搜索时,您需要搜索所有索引.

*"为了一次强制执行一个写入程序,这意味着IndexWriter或IndexReader执行删除或更改规范,Lucene使用基于文件的锁定:如果索引中存在锁定文件(缺省情况下为write.lock)目录,编写器当前打开索引.任何在同一索引上创建另一个编写器的尝试都会遇到LockObtainFailedException.这是一个重要的保护机制,因为如果在一个索引上意外创建了两个编写器,它将很快导致指数腐败."

第2.11.3节,Lucene在行动,第二版,Michael McCandless,Erik Hatcher和OtisGospodnetić,2010