近实时搜索(near-real-time)可以搜索IndexWriter还未commit的内容,介于immediate和eventual之间,在数据比较大、更新较频繁的情况下使用。本文主要来介绍下如何使用,其原理还没弄透,改天再续。本文代码基于lucene 4.10

IndexReader的重建

想要看到新的结果就需要重新打开一个IndexReader,DirectoryReader提供了DirectoryReader openIfChanged(DirectoryReader oldReader)函数,只有索引有变化时才建立新reader(不是完全打开一个new reader,会复用old reader的一些资源,并入新索引,降低一些开销), 否则返回oldReader。

IndexWriter writer = new IndexWriter(ramDir, writerConfig);
//IndexReader,基于IndexWriter打开的IndexReader
IndexReader reader = DirectoryReader.open(writer, true);
IndexSearcher searcher = new IndexSearcher(reader);
//update index
//openIfChanged,如果有提交或未提交的变化,就打开新的indexreader。记住关闭old reader
IndexReader newReader = DirectoryReader.openIfChanged((DirectoryReader) reader, writer, true);
if (reader != newReader) {
searcher = new IndexSearcher(newReader);
reader.close();
}

使用过程:DirectoryReader尝试打开新IndexReader;判断是否获得新Reader;如果成功,关闭老reader。


SearchManager

在实际应用中,会并行的进行搜索、建索引、打开新Reader、关闭老reader,操作比较复杂还有线程安全问题。为了简化使用流程,lucene提供了SearcherManager extends ReferenceManager<IndexSearcher>管理IndexReader的重建和关闭,保证了线程安全,封装了IndexSearcher的生成。主要提供如下三个接口:

  • acquire获取当前已打开的最新IndexSearcher
  • release释放不用的引用,本质调的是IndexReader.close(),当一个IndexReader内部的引用计数为0时,会关闭自己释放资源。
  • maybeRefresh,尝试打开新的IndexReader,本质调用的是DirectoryReader.openIfChanged
ReferenceManager<IndexSearcher> searcherManager = new SearcherManager(writer, true, new SearcherFactory());
SearchersearcherManager.maybeRefresh()
IndexSearcher searcher = searcherManager.acquire();
//after using,释放掉
searcherManager.release(searcher);
searcherManager.close();


ControlledRealTimeReopenThread

如上,如果想获得最新的searcher,就需要周期性的调用maybeRefresh来更新searcher引用。Lucene提供了ControlledRealTimeReopenThread线程工具类来负责周期性的打开ReferenceManager(调用ReferenceManager.maybeRefresh)。该线程类控制打开间隔比较灵活,当有外部用户在等待重新打开Searcher时就按最小时间间隔等待,如果没有用户着急获取新Searcher,则等待最大时间间隔后再打开。其构造函数如下:

ControlledRealTimeReopenThread(TrackingIndexWriter writer, ReferenceManager<T> manager,
double targetMaxStaleSec, double targetMinStaleSec)//单位秒

如何判断是否有人等待?

TrackingIndexWriter封装了IndexWriter,为每次更新索引的操作赋予一个标记(generation,代数),递增变化。用户使用ControlledRealTimeReopenThread.waitForGeneration告诉其期望获得更新代数,ControlledRealTimeReopenThread记录了当前已打开的代数,当期望更新代数大于已打开代数时,就表示有用户期望获得最新Search。

如果想利用TrackingIndexWriter提供的代数概念,每次使用IndexWriter都要经过TrackingIndexWriter,否则代数没意义。但是如果只希望每隔10s打开一次新searcher,并不在意某次更新快速看到,那就可以忽略TrackingIndexWriter,ControlledRealTimeReopenThread就退化为一个clock线程。

ControlledRealTimeReopenThread th = new ...;
th.start();
th.waitForGeneration(targetGen);

Lucene系列-近实时搜索(1)的更多相关文章

  1. 【Lucene】近实时搜索

    近实时搜索:可以使用一个打开的IndexWriter快速搜索索引的变更内容,而不必首先关闭writer,或者向该writer提交:这是2.9版本之后推出的新功能. 代码示例(本例参考<Lucen ...

  2. 剖析Elasticsearch集群系列之三:近实时搜索、深层分页问题和搜索相关性权衡之道

    转载:http://www.infoq.com/cn/articles/anatomy-of-an-elasticsearch-cluster-part03 近实时搜索 虽然Elasticsearch ...

  3. Lucene.net 实现近实时搜索(NRT)和增量索引

    Lucene做站内搜索的时候经常会遇到实时搜索的应用场景,比如用户搜索的功能.实现实时搜索,最普通的做法是,添加新的document之后,调用 IndexWriter 的 Commit 方法把内存中的 ...

  4. lucene4.5近实时搜索

    近实时搜索就是他能打开一个IndexWriter快速搜索索引变更的内容,而不必关闭writer,或者向writer提交,这个功能是在2.9版本以后引入的,在以前没有这个功能时,必须调用writer的c ...

  5. lucene4之后的近实时搜索实现

    好久没干这块东西了,近几天须要做这个.所以又一次学了一下.首先很感谢孔浩老师,没孔浩老师的视频我也不会进入lucene的殿堂. 老师当时讲的实时搜索还是NRTManager,如今已经都变了,这个类已经 ...

  6. solr 近实时搜索

    摘要: Solr的近实时搜索NRT(Near Real Time Searching)意味着文档可以在索引以后马上可以被查询到. Solr不会因为本次提交而阻塞更新操作,不会等待后台合并操作(merg ...

  7. Solr -- 实时搜索

    在solr中,实时搜索有3种方案 ①soft commit,这其实是近实时搜索,不能完全实时. ②RealTimeGet,这是实时,但只支持根据文档ID的查询. ③和第一种类似,只是触发softcom ...

  8. 【Lucene3.6.2入门系列】第03节_简述Lucene中常见的搜索功能

    package com.jadyer.lucene; import java.io.File; import java.io.IOException; import java.text.SimpleD ...

  9. 关于lucene的IndexSearcher单实例,对于索引的实时搜索

    Lucene版本:3.0 一般情况下,lucene的IndexSearcher都要写成单实例,因为每次创建IndexSearcher对象的时候,它都需要把索引文件加载进来,如果访问量比较大,而索引也比 ...

随机推荐

  1. 配置与使用 Git与Github

    Git与Github的注册.配置及使用方法在网上有详细的教程,不做总结. 这里主要总结我在Git.Github的配置及使用过程中遇到的问题.如下: (1) Git与Github的关系.两者都是版本管理 ...

  2. RSpec shared examples with template methods

    It’s pretty common to have multiple tests that are nearly the same. In one app, we support bidding o ...

  3. KMP详解

    原文: http://blog.csdn.net/v_july_v/article/details/7041827 从头到尾彻底理解KMP 1. 引言 本KMP原文最初写于2年多前的2011年12月, ...

  4. Win7 64位命令行编译cuda及设置Windows显卡响应时间

    在开始菜单中找到Visual Studio 2013 >> Visual Studio Tools 选择86或64版本的VC命令提示符环境,我用的 VS2013 x86 Native To ...

  5. AppFuse3.5对接oracle数据库

    AppFuse是一个使用Java语言开发web应用系统的集成框架.java开发人员最头痛的事情就是面对大量的框架不知该如何选择.这些框架性能如何,兼容性如何等等都需要筛选比较.Appfuse作者Mat ...

  6. ruby 学习笔记 2 -变量

    变量 在ruby的世界里,变量有5种,全局变量 局部变量 实例变量 常量 类变量以及伪变量 常用的: 全局: 在全局使用,使用$开头,因为是全局的,所以在任何的代码例子中都可以改变其值,造成混乱,所以 ...

  7. C#中调用python方法

    最近因为项目设计,有部分使用Python脚本,因此代码中需要调用python方法. 1.首先,在c#中调用python必须安装IronPython,在 http://ironpython.codepl ...

  8. nil、Nil、NULL和NSNull的理解

    http://blog.sina.com.cn/s/blog_4930f8e60101h71b.html 其实早就想研究一下nil.Nil.NULL和NSNull之间的区别,只是工作上除了nil,其它 ...

  9. idea中maven报错:无效的目标发行版: 1.8

    1.project.pom中修改版本 <maven.compiler.source>1.7</maven.compiler.source><maven.compiler. ...

  10. Hive几种数据导出方式

    Hive几种数据导出方式 今天我们再谈谈Hive中的几种不同的数据导出方式.可以根据导出的地方不一样,将这些方式分为三种: (1).导出到本地文件系统: (2).导出到HDFS中: (3).导出到Hi ...