Lucene .Net,我需要关闭 IndexWriter 吗
Lucene .Net, do i need to close IndexWriter
我们遇到 Lucene .Net
抛出 LockObtainFailedException
的锁定问题。这是一个多租户站点,每个客户在磁盘上都有自己的物理搜索索引,并使用 static
列表 IndexWriters
,每个索引一个来控制更改。
我们在 IndexWriter
上调用以下函数
AddDocument();
DeleteDocuments();
DeleteAll();
Optimize();
Commit();
我注意到我们从未在 IndexWriter
上调用 Close()
或 Dispose()
,我想知道这是否是好的做法,是否可能是问题的原因。
谢谢戴夫
当您不再需要该对象时使用 Close/Dispose 总是一个好主意。开发人员公开这些方法是有原因的。通常,文档会在何时使用这些方法时提供额外提示。
我还建议在 using
块中使用每个 IDisposeable
对象,它只调用 Dispose()
.
这使对象能够清理和释放资源。在框架对象的情况下,这并不重要,因为垃圾收集器迟早会关心,但在系统对象或句柄(如文件系统句柄)的情况下,Dispose
变得很重要。这些句柄可能会保持打开状态。
在 Lucene IndexWriter 的情况下我不是很确定,但是当它使用文件作为索引时(这是我假设的),那么你就有理由调用 Dispose
.
当 handles/connections/etc 保持打开状态时,可能会导致此类异常。所以,是的,你应该使用 Close()
/Dispose()
文档说是的,但只有当您终止应用程序本身时才会如此 - 否则,不会。这是 Lucene.Net 4.8 中 IndexWriter.Dispose 的文档:
Commits all changes to an index, waits for pending merges to complete,
and closes all associated files.
This is a "slow graceful shutdown" which may take a long time ...
Note that this may be a costly operation, so, try to re-use a single
writer instead of closing and opening a new one. See Commit()
for
caveats about write caching done by some IO devices.
https://github.com/apache/lucenenet/blob/master/src/Lucene.Net/Index/IndexWriter.cs#L996
因此,您应该调用 .Dispose()
,但通常只在您关闭应用程序时调用一次。
您已经在致电 .Commit()
,他们建议您改用此电话。我猜你的问题实际上与线程有关。我只是在学习 Lucene,但如果我处于你的位置,我会尝试在对 Lucene 的任何写入调用周围放置一个标准的 .Net 锁,以便一次只有一个线程可以访问写入。如果它解决了您的问题,您就知道它正在线程化。
锁非常痛苦,而且 Lucene 写入可能需要很长时间,所以如果锁解决了这个问题,它可能会引入其他问题,例如 2 个线程尝试写入和一个挂起或失败,具体取决于您的代码编写方式。如果确实出现这种情况,您可能想要实现一个写队列,以便线程可以快速将他们想要写入的内容移交给像 ConcurrentQueue 这样的廉价数据结构,然后让那些写操作启动写操作,如果 none是 运行,并继续出列直到所有内容都写完 - 然后返回睡眠。
我们遇到 Lucene .Net
抛出 LockObtainFailedException
的锁定问题。这是一个多租户站点,每个客户在磁盘上都有自己的物理搜索索引,并使用 static
列表 IndexWriters
,每个索引一个来控制更改。
我们在 IndexWriter
AddDocument();
DeleteDocuments();
DeleteAll();
Optimize();
Commit();
我注意到我们从未在 IndexWriter
上调用 Close()
或 Dispose()
,我想知道这是否是好的做法,是否可能是问题的原因。
谢谢戴夫
当您不再需要该对象时使用 Close/Dispose 总是一个好主意。开发人员公开这些方法是有原因的。通常,文档会在何时使用这些方法时提供额外提示。
我还建议在 using
块中使用每个 IDisposeable
对象,它只调用 Dispose()
.
这使对象能够清理和释放资源。在框架对象的情况下,这并不重要,因为垃圾收集器迟早会关心,但在系统对象或句柄(如文件系统句柄)的情况下,Dispose
变得很重要。这些句柄可能会保持打开状态。
在 Lucene IndexWriter 的情况下我不是很确定,但是当它使用文件作为索引时(这是我假设的),那么你就有理由调用 Dispose
.
当 handles/connections/etc 保持打开状态时,可能会导致此类异常。所以,是的,你应该使用 Close()
/Dispose()
文档说是的,但只有当您终止应用程序本身时才会如此 - 否则,不会。这是 Lucene.Net 4.8 中 IndexWriter.Dispose 的文档:
Commits all changes to an index, waits for pending merges to complete, and closes all associated files.
This is a "slow graceful shutdown" which may take a long time ...
Note that this may be a costly operation, so, try to re-use a single writer instead of closing and opening a new one. See
Commit()
for caveats about write caching done by some IO devices.
https://github.com/apache/lucenenet/blob/master/src/Lucene.Net/Index/IndexWriter.cs#L996
因此,您应该调用 .Dispose()
,但通常只在您关闭应用程序时调用一次。
您已经在致电 .Commit()
,他们建议您改用此电话。我猜你的问题实际上与线程有关。我只是在学习 Lucene,但如果我处于你的位置,我会尝试在对 Lucene 的任何写入调用周围放置一个标准的 .Net 锁,以便一次只有一个线程可以访问写入。如果它解决了您的问题,您就知道它正在线程化。
锁非常痛苦,而且 Lucene 写入可能需要很长时间,所以如果锁解决了这个问题,它可能会引入其他问题,例如 2 个线程尝试写入和一个挂起或失败,具体取决于您的代码编写方式。如果确实出现这种情况,您可能想要实现一个写队列,以便线程可以快速将他们想要写入的内容移交给像 ConcurrentQueue 这样的廉价数据结构,然后让那些写操作启动写操作,如果 none是 运行,并继续出列直到所有内容都写完 - 然后返回睡眠。