`
forfuture1978
  • 浏览: 413030 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

有关Lucene的问题(7):用Lucene构建实时的索引

阅读更多

由于前一章所述的Lucene的事务性,使得Lucene可以增量的添加一个段,我们知道,倒排索引是有一定的格式的,而这个格式一旦写入是非常难以改变的,那么如何能够增量建索引呢?Lucene使用段这个概念解决了这个问题,对于每个已经生成的段,其倒排索引结构不会再改变,而增量添加的文档添加到新的段中,段之间在一定的时刻进行合并,从而形成新的倒排索引结构。

然而也正因为Lucene的事务性,使得Lucene的索引不够实时,如果想Lucene实时,则必须新添加的文档后IndexWriter需要commit,在搜索的时候IndexReader需要重新的打开,然而当索引在硬盘上的时候,尤其是索引非常大的时候,IndexWriter的commit操作和IndexReader的open操作都是非常慢的,根本达不到实时性的需要。

好在Lucene提供了RAMDirectory,也即内存中的索引,能够很快的commit和open,然而又存在如果索引很大,内存中不能够放下的问题。

所以要构建实时的索引,就需要内存中的索引RAMDirectory和硬盘上的索引FSDirectory相互配合来解决问题。

1、初始化阶段

首先假设我们硬盘上已经有一个索引FileSystemIndex,由于IndexReader打开此索引非常的慢,因而其是需要事先打开的,并且不会时常的重新打开。

我们在内存中有一个索引MemoryIndex,新来的文档全部索引到内存索引中,并且是索引完IndexWriter就commit,IndexReader就重新打开,这两个操作时非常快的。

如下图,则此时新索引的文档全部能被用户看到,达到实时的目的。

 

2、合并索引阶段

然而经过一段时间,内存中的索引会比较大了,如果不合并到硬盘上,则可能造成内存不够用,则需要进行合并的过程。

当然在合并的过程中,我们依然想让我们的搜索是实时的,这是就需要一个过渡的索引,我们称为MergingIndex。

一旦内存索引达到一定的程度,则我们重新建立一个空的内存索引,用于合并阶段索引新的文档,然后将原来的内存索引称为合并中索引,并启动一个后台线程进行合并的操作。

在合并的过程中,如果有查询过来,则需要三个IndexReader,一个是内存索引的IndexReader打开,这个过程是很快的,一个是合并中索引的IndexReader打开,这个过程也是很快的,一个是已经打开的硬盘索引的IndexReader,无需重新打开。这三个IndexReader可以覆盖所有的文档,唯一有可能重复的是,硬盘索引中已经有一些从合并中索引合并过去的文档了,然而不用担心,根据Lucene的事务性,在硬盘索引的IndexReader没有重新打开的情况下,背后的合并操作它是看不到的,因而这三个IndexReader所看到的文档应该是既不少也不多。合并使用IndexWriter(硬盘索引).addIndexes(IndexReader(合并中索引)),合并结束后Commit。

如下图:

 

 

3、重新打开硬盘索引的IndexReader

当合并结束后,是应该重新打开硬盘索引的时候了,然而这是一个可能比较慢的过程,在此过程中,我们仍然想保持实时性,因而在此过程中,合并中的索引不能丢弃,硬盘索引的IndexReader也不要动,而是为硬盘索引打开一个临时的IndexReader,在打开的过程中,如果有搜索进来,返回的仍然是上述的三个IndexReader,仍能够不多不少的看到所有的文档,而将要打开的临时的IndexReader将能看到合并中索引和原来的硬盘索引所有的文档,此IndexReader并不返回给客户。如下图:

 

4、替代IndexReader

当临时的IndexReader被打开的时候,其看到的是合并中索引的IndexReader和硬盘索引原来的IndexReader之和,下面要做的是:

(1) 关闭合并中索引的IndexReader

(2) 抛弃合并中索引

(3) 用临时的IndexReader替换硬盘索引原来的IndexReader

(4) 关闭硬盘索引原来的IndexReader。

上面说的这几个操作必须是原子性的,如果做了(2)但没有做(3),如果来一个搜索,则将少看到一部分数据,如果做了(3)没有做(2)则,多看到一部分数据。

所以在进行上述四步操作的时候,需要加一个锁,如果这个时候有搜索进来的时候,或者在完全没有做的时候得到所有的IndexReader,或者在完全做好的时候得到所有的IndexReader,这时此搜索可能被block,但是没有关系,这四步是非常快的,丝毫不影响替代性。

如下图:

 

经过这几个过程,又达到了第一步的状态,则进行下一个合并的过程。

5、多个索引

有一点需要注意的是,在上述的合并过程中,新添加的文档是始终添加到内存索引中的,如果存在如下的情况,索引速度实在太快,在合并过程没有完成的时候,内存索引又满了,或者硬盘上的索引实在太大,合并和重新打开要花费太长的时间,使得内存索引以及满的情况下,还没有合并完成。

为了处理这种情况,我们可以拥有多个合并中的索引,多个硬盘上的索引,如下图:

 

  • 新添加的文档永远是进入内存索引
  • 当内存索引到达一定的大小的时候,将其加入合并中索引链表
  • 有一个后台线程,每隔一定的时刻,将合并中索引写入一个新的硬盘索引中取。这样可以避免由于硬盘索引过大而合并较慢的情况。硬盘索引的IndexReader也是写完并重新打开后才替换合并中索引的IndexReader,新的硬盘索引也可保证打开的过程不会花费太长时间。
  • 这样会造成硬盘索引很多,所以,每隔一定的时刻,将硬盘索引合并成一个大的索引。也是合并完成后方才替换IndexReader

大家可能会发现,此合并的过程和Lucene的段的合并很相似。然而Lucene的一个函数IndexReader.reopen一直是没有实现的,也即我们不能选择哪个段是在内存中的,可以被打开,哪些是硬盘中的,需要在后台打开然后进行替换,而IndexReader.open是会打开所有的内存中的和硬盘上的索引,因而会很慢,从而降低了实时性。

  • 大小: 26.2 KB
  • 大小: 45.1 KB
  • 大小: 71.2 KB
  • 大小: 42.2 KB
  • 大小: 44.9 KB
14
6
分享到:
评论
7 楼 hanyu332 2012-12-25  
貌似是看明白了,但是还是不太明白
提供搜索的是哪个reader,内存的还是硬盘的?
这样说来内存的reader只管更新,这样他的索引就不是全部吧?不是这样
内存reader提供查询,那还是有内存容量不够的问题吧?
如果提供搜索的是硬盘的索引?就每次需要重建索引,应该也不是这种方式
恕我愚昧,能否详细说一下
6 楼 tonytony3 2011-11-27  
--------------update one index
opendirectory time : 15
new indexwritercfg time : 47
new indexwriter time :  94
  update doc time :  78

-------------- add one index
opendirectory time : 16
new indexwritercfg time : 47
new indexwriter time :  62
add doc time :  702
the indexed count is : 18528
index 总时间 : 702  毫秒

---------------del one index
opendirectory time : 16
new indexwritercfg time : 31
new indexwriter time :  78
  del doc time :  47


2G 索引,算不算百万级,算不算实时  [每次都indexWriter.close();]再重新打开硬盘索引的   [重建 全部 索引为20分钟]
5 楼 tonytony3 2011-11-23  
不好意思,小菜一个

reopen就算实现,只是实现了实时搜索,而没有实时索引,也是不行的,是不是这 样啊?

[看到INDEXREADER的5个实现类里后三个的API里已 实现了REOPEN]
4 楼 tonytony3 2011-11-23  
可能,我的确是想偷懒,Lucene3.4 是不是有个 IndexReader reopen()

是实时的打开,是不是就不用你这种方式了.
3 楼 shiwei8097 2010-11-09  
你好,在第一步里,事先打开硬盘级indexreader,但是直接使用它,搜索的性能怎么保证呢??
2 楼 herry 2010-06-24  
如果是索引的删除呢?如何能够保持实时性?
1 楼 yangfuchao418 2010-06-09  
    

相关推荐

    有关Lucene的问题(8):用Lucene构建实时索引的文档更新问题[整理].pdf

    有关Lucene的问题(8):用Lucene构建实时索引的文档更新问题[整理].pdf

    lucene 对 xml建立索引

    lucene 对 xml建立索引 建立索引就是怎么简单 呵呵

    lucene 7索引查看工具 -luke-7.2.0-luke-release.zip

    Luke是一个方便的索引查看和诊断工具,可以访问Lucene构建的索引文件,显示和修改某些索引内容。luke 7.2.0 支持最新的 lucene7 索引查看 github地址:https://github.com/DmitryKey/luke/releases

    lucene-solr:Apache Lucene和Solr开源搜索软件

    Apache Solr是使用Java编写并使用Apache Lucene的企业搜索平台。 主要功能包括全文搜索,索引复制和分片以及结果分面和突出显示。 在线文件 该自述文件仅包含基本的安装说明。 有关更全面的文档,请访问: Lucene...

    lucene 索引小示例

    NULL 博文链接:https://blaiu.iteye.com/blog/588054

    lucene:lucene构建索引,从HelloWorld到项目具体使用

    lucene构建索引,从HelloWorld到项目具体使用 ====================项目一:=================================== qianjun.lucene.first ====================项目二:=================================== qianjun....

    Lucene检索文本,建立索引

    用Lucene检索文本,建立索引,用struts构建web程序框架

    lucene例子

    到 2009 年 7 月 30 日止,用于 Java™ 编程语言的最新版 Lucene 为 V2.4.1。 Lucene 功能众多: 拥有强大、准确、有效的搜索算法。 计算每个文档匹配给定查询的分数,并根据分数返回最相关的文档。 支持许多强大的...

    基于lucene的Swing全文索引构建于查询工具及源程序

    基于lucene的Swing全文索引构建于查询工具及源程序,有源程序以及做好的工具,非常适合初学者学习学习lucene

    lucene-query-string-builder:使用基本功能构建复杂的Lucene查询字符串

    使用小型纯函数轻松构建您的Lucene字符串查询。 想象一下,有一个利用Lucene在(索引的)数据库上执行查询的API。 在这种情况下,您可能希望在客户端/前端上生成lucene查询字符串。 用法部分显示了如何利用此库...

    Lucene IndexApplication:使用lucene索引文本文档-开源

    自动和安排 Lucene 搜索索引的构建。 用于记录系统消息的通用日志框架。 您可以为严重和非严重错误和消息配置设置。 排名搜索——最好的结果首先返回许多强大的查询类型:短语查询、通配符查询、邻近查询、范围查询...

    Lucene中的FST算法描述

    描述了Lucene中如何使用FST算法构建term的内存索引,使用了很多图,直观的展现了FST图的构建流程,能够对想了解lucene内部实现机制原理的同学有帮助。

    Lucene示例 BM25相似度计算

    用lucene 4.7.1做的一个Lucene构建索引、进行查询,对比默认的相似度计算与BM25相似度计算输出结果的示例。内容不多,供新手参考

    lucene索引

    基于数据库的lucene3。索引构建类代码

    使用lucene构建一个简单的搜索引擎

    全文检索首先将要查询的目标文档中的词提取出来,组成索引,通过查询索引达到搜索目标文档的目的。这种先建立索引,再对索引进行搜索的过程就叫全文检索(Full-...这是一个使用lucene开源框架编写的一个简单的搜索功能

    全文检索 lucene

    作为一个开放源代码项目,Lucene从问世之后,引发了开放源代码社群的巨大反响,程序员们不仅使用它构建具体的全文检索应用,而且将之集成到各种系统软件中去,以及构建Web应用,甚至某些商业软件也采用了Lucene作为...

    Lucene文件检索实战项目

    Lucene从问世之后,引发了开放源代码社群的巨大反响,程序员们不仅使用它构建具体的全文检索应用,而且将之集成到各种系统软件中去,以及构建Web应用,甚至某些商业软件也采用了Lucene作为其内部全文检索子系统的...

    Lucene搜索引擎开发权威经典 光盘

    介绍了Lucene的基础知识,包括Lucene的历史和发展情况、使用Lucene创建索引和执行搜索的基本方法以及中文分词的应用,最后做了两个应用项目。第2部分:数据解析。介绍解析不同格式数据(如Word、PDF等)的方法,包括...

    基于Lucene_Heritrix的垂直搜索引擎的研究与应用

    Lucene是一个用Java写的全文索引引擎工具包,访问索引时间快,支持多用户访问,可以跨平台使用。Heritrix是一个由Java开发的、开源的Web网络爬虫,用户可以使用它从网络上抓取想要的资源。探讨了Lucene和Heritrix在构建...

    Heritrix lucene开发自己的搜索引擎(源码)1

    从产品信息文件构建索引的源代码 数据库操作类的源代码 基于Spring的业务层管理 检索的业务类源代码 检索的DAO源代码 检索的分页实现源代码 检索的AJAX实现源代码 安装:直接在Eclipse中选取“import->...

Global site tag (gtag.js) - Google Analytics