Lucene.Net,我需要关闭IndexWriter吗

本文关键字:IndexWriter Net Lucene | 更新日期: 2023-09-27 17:59:39

我们遇到了Lucene .Net抛出LockObtainFailedException的锁定问题。这是一个多租户网站,每个客户在光盘上都有自己的物理搜索索引,并使用IndexWritersstatic列表,每个索引一个以控制更改。

我们在IndexWriter 上调用以下函数

AddDocument();
DeleteDocuments();
DeleteAll();
Optimize();
Commit();

我注意到,我们从未在IndexWriter上调用Close()Dispose(),我想知道这是否是一种良好的做法,是否可能是问题的原因。

感谢Dave

Lucene.Net,我需要关闭IndexWriter吗

文档会说是,但只有在您关闭应用程序本身时才会这样做,否则就不会。以下是IndexWriter的文档。在Lucene中处理。净4.8:

提交对索引的所有更改,等待挂起的合并完成,并关闭所有关联的文件。

这是一个"缓慢而优雅的关闭",可能需要很长时间。。。

请注意,这可能是一项成本高昂的操作,因此,请尝试重复使用单个作者,而不是关闭并打开一个新的。参见Commit()关于某些IO设备进行写缓存的注意事项。

https://github.com/apache/lucenenet/blob/master/src/Lucene.Net/Index/IndexWriter.cs#L996

因此,您应该调用.Dispose(),但通常在关闭应用程序时只调用一次。然而,目前还不清楚是否需要Dispose()它的底层对象。

您已经在拨打.Commit(),他们建议您改为拨打。我想你的问题实际上与线程有关。我只是在学习Lucene,但如果我处于你的位置,我会尝试制定一个标准。Net锁定对Lucene的任何写入调用,这样一次只有一个线程可以访问写入。如果它解决了你的问题,你就知道它是线程。

锁是非常痛苦的,Lucene写入可能需要很长时间,所以如果锁解决了这个问题,它可能会引入其他问题,比如两个线程试图写入,一个线程挂起或失败,这取决于代码的编写方式。如果真的出现了这种情况,你可能想实现一个写队列,这样线程就可以快速地将他们想要写入的内容交给ConcurrentQueue这样的廉价数据结构,然后让这些写操作在没有运行的情况下启动写操作,并保持出队,直到所有内容都写出来,然后返回睡眠状态。

在不再需要对象时使用Close/Dispose总是一个好主意。开发人员公开这些方法是有原因的。通常,文档会在使用这些方法时提供额外提示。

我还建议使用using-块中的每个IDisposeable-对象,它只调用Dispose()

这使对象能够清理和释放资源。对于框架对象,这并不重要,因为垃圾收集器迟早会关心它,但对于系统对象或像文件系统句柄Dispose这样的句柄,这就变得很重要了。这些把手可能一直打开。

在Lucene IndexWriter的情况下,我不能完全确定,但当它使用一个文件作为索引时(我认为这是),那么就有理由调用Dispose

当句柄/连接等保持打开时,可能会导致此类异常。所以,是的,您应该使用Close()/Dispose()