lucene4及以上如何做到近实时搜索

请支持原创博客 http://blog.youkuaiyun.com/cl59452/article/details/38408741

lucene2.9 之后推出了nrtmanager  近实时搜索,但是很多人在lucene4.x 中找不到了,我通过查阅apache 的log 发现,lucene已经用ControlledRealTimeReopenThread将nrtmanager替代了具体的实现过程如下:

   

[java]  view plain copy
  1. public class IndexUtil {  
  2.       
  3.     private SearcherManager mgr;  
  4.     private IndexWriter writer;  
  5.     private TrackingIndexWriter tkWriter;  
  6.     private ControlledRealTimeReopenThread<IndexSearcher> crtThread;  
  7. //    private String path ;  
  8.       
  9.     public IndexUtil(String path){  
  10.         try {  
  11.             Directory fsDir = FSDirectory.open(new File(path));  
  12.             //创建writer  
  13.             writer = new IndexWriter(fsDir,new IndexWriterConfig(Version.LUCENE_47,new IKAnalyzer(true)));  
  14.             //新建SearcherManager  
  15.             //true 表示在内存中删除,false可能删可能不删,设为false性能会更好一些  
  16.             mgr = new SearcherManager(writer,false,new SearcherFactory());  
  17.             //ControlledRealTimeReopenThread 构造是必须有的,主要将writer装,每个方法都没有commit 操作。  
  18.             tkWriter = new TrackingIndexWriter(writer);//为writer 包装了一层  
  19.             //创建线程,线程安全的,我们不须处理      
  20.             crtThread = new ControlledRealTimeReopenThread<IndexSearcher>(tkWriter, mgr, 5.00.025);  
  21.             crtThread.setDaemon(true);//设为后台进程  
  22.             crtThread.setName("我是好人");  
  23.             crtThread.start();//启动线程  
  24. //            crtThread.  
  25.         } catch (IOException e) {  
  26.             e.printStackTrace();  
  27.         }  
  28.     }  
  29.       
  30.       
  31.     public void search(){  
  32.         IndexSearcher searcher = null;  
  33.         try {  
  34.   
  35.             //更新看看内存中索引是否有变化如果,有一个更新了,其他线程也会更新  
  36.   
  37.            mgr.maybeRefresh();  
  38.   
  39.             //利用acquire 方法获取search,执行此方法前须执行maybeRefresh  
  40.             searcher = mgr.acquire();  
  41.            IndexSearcher tr = mgr.refreshIfNeeded(searcher);  
  42.   
  43.             String fields[] = {"body","name"};  
  44.             QueryParser qp = new MultiFieldQueryParser(Version.LUCENE_47,fields,new IKAnalyzer(true));  
  45.             Query query =new TermQuery(new Term("id""2"));// qp.parse("中国");  
  46.             TopDocs tds = searcher.search(query, 5);  
  47.             ScoreDoc[] sds = tds.scoreDocs;  
  48.             for(ScoreDoc sd:sds){  
  49.                 Document d = searcher.doc(sd.doc);  
  50.                 System.out.println(d.get("name")+d.get("body")/*+d.get("id")*/);  
  51.             }  
  52.         } catch (IOException e) {  
  53.             e.printStackTrace();  
  54.         } /*catch (ParseException e) { 
  55.             e.printStackTrace(); 
  56.         }*/finally{  
  57.   
  58.             try {  
  59.   
  60.                //释放searcher,  
  61.                 mgr.release(searcher);  
  62.             } catch (IOException e) {  
  63.                 e.printStackTrace();  
  64.             }  
  65.             System.out.println("------------------------------------------------------------------------------------------------");  
  66.         }  
  67.   
  68.     }  
  69. }  
实现原理:
只有Index Writer上的commit操作才会导致ram directory上的数据完全同步到文件。 Index Writer提供了实时获得reader的API,这个调用将导致flush操作,生成新的 segment,但不会commit(fsync),从而减少 了IO。新的segment被加入到新生成的

reader里。从返回的reader里,可以看到更新。所以,只要每次新的搜索都从IndexWriter获得一个新的reader,就可以搜索到最新的内容。这一操作的开销仅仅是flush,相对commit来说,开销很小。

Lucene的index组织方式为一个index目录下的多个segment。新的doc会加入新的segment里,这些新的小segment每隔一段时间就合并起来。因为合并,总的segment数

量保持的较小,总体search速度仍然很快。为了防止读写冲突,lucene只创建新的segment,并在任何active的reader不在使用后删除掉老的segment。

flush是把数据写入到操作系统的缓冲区,只要缓冲区不满,就不会有硬盘操作。

commit是把所有内存缓冲区的数据写入到硬盘,是完全的硬盘操作。

重量级操作。这是因为,Lucene索引中最主要的结构posting通过VINT和delta的格式存

储并紧密排列。合并时要对同一个term的posting进行归并排序,是一个读出,合并再生

成的过程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值