LockObtainFailedException使用solr更新Lucene搜索索引

时间:2011-03-16 15:55:49

标签: lucene solr

我搜索了很多内容。大多数问题都是由JVM崩溃后留下的锁引起的。这不是我的情况。

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

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

去世
  

引起:   org.apache.lucene.store.LockObtainFailedException:   锁获得超时:   NativeFSLock @ / ... / lucene的-ff783c5d8800fd9722a95494d07d7e37-write.lock

我已经在solrconfig.xml

中调整了锁定超时
<writeLockTimeout>20000</writeLockTimeout>
<commitLockTimeout>10000</commitLockTimeout>

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

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

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

val rsp = req.process(solrServer)

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进程起到很好的作用,并且他们会等待另一个正在编写。

2 个答案:

答案 0 :(得分:13)

我假设你正在做类似的事情:

writer1.writeSomeStuff();
writer2.writeSomeStuff();  // this one doesn't write

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

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

writer1.writeSomeStuff();
writer1.close();
writer2.open();
writer2.writeSomeStuff();
writer2.close();

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

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

我不确定您的用例是什么,但另一个可能的答案是看Solr's Recommendations来管理多个索引。特别是热插拔核心的能力可能会引起人们的兴趣。

答案 1 :(得分:6)

&GT;&GT; 但是你有多个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