【问题标题】:How to safely close an IndexReader?如何安全地关闭 IndexReader?
【发布时间】:2012-07-08 11:57:51
【问题描述】:

我的问题很简单,当使用IndexReader.openIfChanged (reader)替换之前的reader,如何安全关闭oldReader

这里是代码:(使用 Lucene 3.5)

IndexReader newReader=IndexReader.openIfChanged(reader);
if(newReader!=null){
    IndexReader oldReader=reader;
    IndexSearcher oldSearcher=searcher;

    reader=newReader;
    searcher=new IndexSearcher(newReader);

    oldSearcher.close();
    oldReader.close();//or oldReader.decRef(),result is the same
}

这段代码在一个守护线程中,每5秒运行一次

IndexReader instance(reader object) 是全局唯一的

由于这个变化,我得到一个例外:

org.apache.lucene.store.AlreadyClosedException: this IndexReader is closed
    at org.apache.lucene.index.IndexReader.ensureOpen(IndexReader.java:297)
    at org.apache.lucene.index.IndexReader.getSequentialSubReaders(IndexReader.java:1622)
    at org.apache.lucene.search.TermQuery$TermWeight.scorer(TermQuery.java:98)
    at org.apache.lucene.search.BooleanQuery$BooleanWeight.scorer(BooleanQuery.java:298)
    at org.apache.lucene.search.BooleanQuery$BooleanWeight.scorer(BooleanQuery.java:298)
    at org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:577)
    at org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:517)
    at org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:487)
    at org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:400)
    at org.zenofo.index.IndexManager.query(IndexManager.java:392)
    ...

IndexManager.java:392 使用reader 对象(IndexReader 实例,全局唯一)

IndexManager.query方法有大量并发请求,所有请求使用全局唯一的IndexReader实例(reader对象)

我需要关闭oldReader 只是因为:

参考:

我该如何解决这个问题?

【问题讨论】:

  • 您确定在调用 openIfChanged 之前阅读器没有关闭吗?
  • 你的并发设置是什么?如果这段代码可以同时执行,那么它可能有很多问题。无论如何,你不应该自己实现这个,因为 Lucene 已经 provides its own SearcherManager
  • @vikas 我的问题描述了错误,我必须修改并重写问题
  • @MarkoTopolnik 感谢您的回答,oldReader.close() 包含一个守护线程,IndexReader 实例是全局唯一的,IndexManager.query 的方法出现异常,IndexManager.query 支持并发(在我的问题之前描述错误,我已修复)
  • 一种简单的方法:创建一个对象,其中包含两个 final 字段,分别保存 reader 和 searcher。使用 static volatile var 指向它。在每个索引重新打开时,创建一个新的此类对象并将其放入 var。

标签: java lucene


【解决方案1】:

看看 NRTManager 和 SearcherManager。你真的不必自己处理。

【讨论】:

    【解决方案2】:

    您需要在对public static 变量的写入和随后从其他线程读取它们之间施加happens-before 关系。如果您使用多个 var,则会遇到原子性问题,因此我建议您只使用一个 var,因为这就是您所需要的。

    简单地说,这对你有用:

    public class SearcherManager 
    {
      public static volatile IndexSearcher searcher;
    
      private static void reopen() {
        // your code, just without assignment to reader
      }
    }
    

    关键是volatile 修饰符。确保在写入 var 之前完全初始化所有内容,但在写入之后关闭旧对象 - 换句话说,只需确保按照现在的方式继续执行它 :)

    但是,正如@MJB 在他的回答中指出的那样,您应该真的不要这样做,因为它全部内置于 Lucene 中。查看Javadoc on NRTManagerReopenThread 以获取您需要的所有信息,包括完整的代码示例。

    【讨论】:

      【解决方案3】:

      如果在阅读器 (oldReader) 上工作,我假设搜索器(后来称为 oldSearcher),在这种情况下,当你关闭它时,它也会关闭它使用的阅读器,所以你不需要关闭它, oldSearcher.close() 就足够了。

      【讨论】:

      • 关闭 IndexSearcher 不会关闭底层 IndexReader,除非它使用隐式读取器。 Reference.
      • 你说得对,我就是这么说的——我假设他构建了搜索器,所以它会隐式使用阅读器。
      • 隐式读取器是指通过提供包含索引的目录的路径来创建 IndexSearcher 时。因此,如果 oldSearcher 是使用 this 构造函数创建的,并且稍后从中检索到 reader,它将关闭底层 reader。
      • 好的,@Zenofo,请向我们提供有关您如何创建搜索器的更多信息,以便我们了解我们面临的用例。
      • @shem 感谢回答,我需要关闭oldReader(我在qustion中补充了原因)
      【解决方案4】:

      我根本看不到 oldReader 和 oldSearcher 在做什么!!!! 你不能把它们连同他们的close()一起删除吗? 如果您仍然需要它们,那么我敢打赌 oldSearcher 在某种程度上与 oldReader 相关,因此在 oldSearcher 上调用 close() 也会导致关闭 oldReader 这就是您得到异常的原因 这是全部代码,还是您简化了它?如果是,则首先删除 oldReader 和 oldSearcher

      干杯

      【讨论】:

      • 感谢您的回答,在我的问题描述错误之前,我修复并重写了问题
      • 虽然我坚信第二次 close() 调用是在一个封闭的流上进行的。由第一个 close() 引起。尝试检查 oldReader 上的 ifClosed() 或其他内容,因为其他用户已经提到,oldReader 和 oldSearcher 一个用于初始化另一个,因此关闭其中一个也会关闭另一个
      • 我删除了oldSearcher.close() 只运行oldReader.close() 问题是一样的
      • 好。保持删除/评论。你能检查一下 oldReader 是否已经关闭,因为它看起来像它。也许阅读器已经关闭并将其分配给 oldReader 然后 oldReader 也关闭
      • 你说得对,oldSearcher.close()不重要,但问题是oldReader.close(),在IndexManager.query方法中抛出异常
      【解决方案5】:

      看看 indexreader 引用计数方法。 即当您实例化一个新的 IndexSearcher 时增加引用计数 reader.incRef(); 并在您完成搜索结果后减小它,最好在带有 reader.decRef() 的 try catch 方法的 finally 语句中;

      reader.decRef()在引用数为0时自动关闭阅读器。

      【讨论】:

      • 我强烈建议你看看 lucene in Action book 的第 361-364 页
      猜你喜欢
      • 1970-01-01
      • 2012-05-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-11
      • 1970-01-01
      • 2023-03-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多