lucene IndexReader reOpen 的彻底研究

一直觉得lucene的reopen有问题,今天特地研究了下,顺便熟悉了整个IndexReader的结构体系

IndexReader是一个体系,他是search的核心io之一

org.apache.lucene.index


Class IndexReader

java.lang.Object   org.apache.lucene.index.IndexReader 
Direct Known Subclasses:
FilterIndexReader, MultiReader, ParallelReader

先来看看IndexReader下面的类体系我们平常会使用的三个派生: FilterIndexReader MultiReader ParallelReader


下面来看看我犯错误的reopen:

public IndexReader reopen()                    throws CorruptIndexException,                           IOException

 

之前为什么我错了,我以为这个方法是自省的(根本没有注意它的返回不是void的道理么...),所以我怎么写的?

iSearch.getIndexReader().reopen();

误以为这样就可以reopen,结果总是被投诉没有更新,所以一直觉得更新有问题,实际上是我用法的问题,应该是这样的.

if (iSearch != null) {
// 新修改的reopen方法
try {
IndexReader irOld = this.reOpen(iSearch);
// isearchMap.remove(searchBean.getIsearchName());
isearchMap.put(searchBean.getIsearchName(),
new IndexSearcher(irOld));
} catch (Exception e) {
e.printStackTrace();
} finally {
// 注意要关闭掉原来的iSearch
iSearch.close();
iSearch = null;
logger.info(">>>>>>>>>>>>>one search has been reopen:"
+ searchBean.getIsearchName());
}
}

上面是从程序里截取的看看意思就好了.

但后来发现这样还是不对的,看源码上的说明:
If the index has not changed since this instance was (re)opened, then this
* call is a NOOP and returns this instance. Otherwise, a new instance is
* returned. The old instance is <b>not</b> closed and remains usable.

如果没有改变的话,他会返回null的,这样不得不判断一下,所以代码要这样:

if (iSearch != null) {
// 新修改的reopen方法
try {
IndexReader irOld = reOpen(iSearch);
if (irOld != null) {
// isearchMap.remove(searchBean.getIsearchName());
isearchMap.put(searchBean.getIsearchName(),
new IndexSearcher(irOld));
// 注意要关闭掉原来的iSearch
iSearch.close();
iSearch = null;
}
} catch (Exception e) {
logger.error(e);
} finally {
logger.info(">>>>>>>>>>>>>one search has been reopen:"
+ searchBean.getIsearchName());
}
}

这样可以在索引不变下不产生更多io消耗,那么我们可以这样理解reopn的实质:

首先判断 lastmodify时间,如果被更新了则, new 一个IndexReader, 否则就直接返回null,而操作方法都扔给了用户. 所以官方所谓的reopen能减少消耗说法并不准确,它做的只是在改变时重新连接,但这个他官方文档所说的只更新更新部分有很大不同,现在只是选择性地降低了io,但是如果每次探测时索引都变了就变得没有意义,这样的好吃是,索引的跟踪可以变得更频繁,也不再需要程序过多干预了.

但是目前这个方法写得不够成熟,至少我认为应该更"傻瓜"而不是把那么多细节都扔给开发者.

好了reopen这个新兴方法应该算是彻底搞明白了,原来看似吹嘘的很神的新东西,还是老瓶子装新酒呀,呵呵....

末了,代码再完善下:

if (iSearch != null) {
    // 新修改的reopen方法
    Boolean isNew = false;
    try {
     IndexReader irOld = reOpen(iSearch);
     if (irOld != null) {
      isNew = true;
      // isearchMap.remove(searchBean.getIsearchName());
      isearchMap.put(searchBean.getIsearchName(),
        new IndexSearcher(irOld));
     }
    } catch (Exception e) {
     logger.error(e);
    } finally {
     if (isNew) {
      //保证关闭掉资源,否则连接数一多把机器io挂死
      iSearch.close();
      iSearch = null;
     }
     logger.info(">>>>>>>>>>>>>one search has been reopen:"
       + searchBean.getIsearchName());
    }

你可能感兴趣的:(exception,IO,null,Lucene,search,Class)