`

有关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提供的不同方法以及它们的适用场景。以下是对Lucene删除文档和更新文档的详细讨论。 1. Lucene删除文档的方式: - `IndexReader.deleteDocument...

    lucene5+zoie实现近实时索引

    然而,传统的Lucene在处理大规模数据时,由于其索引构建的离线特性,往往无法满足实时或近实时的索引更新需求。为了解决这个问题,Zoie应运而生。本篇文章将详细介绍如何利用Lucene 5和Zoie来构建一个能够实现实时或...

    Lucene 索引的简单使用

    本篇文章将详细阐述如何使用Lucene来创建和查询索引,帮助你深入理解其核心概念和操作流程。 ### 1. Lucene基本概念 - **文档(Document)**:在Lucene中,一个文档代表你要索引的信息单元,它可以包含多个字段...

    Lucene索引器实例

    以上就是Lucene索引器实例的基本介绍,通过这个实例,我们可以理解到如何使用Lucene来创建、管理和搜索文本索引。在实际项目中,可以根据需求选择合适的存储(如硬盘目录或分布式存储)、优化分析器配置、处理大量...

    lucene 对 xml建立索引

    ### Lucene对XML文档建立索引的技术解析与实践 #### 一、引言 随着互联网技术的迅猛发展,非结构化数据(如XML文档)在企业和组织中的应用日益广泛。如何高效地处理这些非结构化的数据,特别是进行快速检索成为了一...

    Lucene.Heritrix:开发自己的搜索引擎(第2版)

    7. **扩展与高级话题**:可能包括分布式搜索、实时索引更新、近实时搜索,以及如何与其他系统集成,如Solr或Elasticsearch。 这本书是学习如何利用开源工具构建搜索引擎的宝贵资源,适合对搜索引擎技术感兴趣的...

    lucene 索引小示例

    7. **搜索**: 创建IndexReader和IndexSearcher,用以读取索引并执行查询。构造Query对象,例如使用TermQuery匹配特定关键词,然后使用IndexSearcher执行查询。最后,使用HitCollector或TopDocs收集结果。 8. **显示...

    深入 Lucene 索引机制

    《深入 Lucene 索引机制》这篇博文主要探讨了Lucene这个全文搜索引擎的核心索引原理,它在信息检索领域有着广泛的应用。Lucene是一个开源的Java库,它提供了高效、可扩展的文本搜索功能。以下是对Lucene索引机制的...

    基于lucene技术的增量索引

    **基于Lucene技术的增量索引** 在信息技术领域,全文搜索引擎是处理大量数据查询的关键工具。Apache Lucene是一个开源的全文检索库,被广泛应用于构建高效、可扩展的搜索功能。本文将深入探讨如何利用Lucene实现...

    lucene5.X与lucene3.60的版本差异

    《Lucene 5.x与3.6.0版本差异详解》 Lucene作为一个强大的全文搜索引擎库,其每个版本的更新都带来了一系列的变化和优化。...通过理解这些变化,开发者可以更有效地利用Lucene构建高效、稳定的全文搜索系统。

    lucene索引查看工具及源码

    在使用 Lucene 进行信息检索时,有时我们需要对建立的索引进行查看、调试或分析,这时就需要借助 Lucene 的索引查看工具。 Luke 是一个非常实用的 Lucene 索引浏览器,全称为 Lucidworks Luke。它允许用户以图形化...

    lucene全文检索简单索引和搜索实例

    《Lucene全文检索:简单索引与搜索实例详解》 Lucene是Apache软件基金会的开源项目,是一款强大的全文检索库,被广泛应用于Java开发中,为开发者提供了构建高性能搜索引擎的能力。在本文中,我们将深入探讨如何基于...

    Lucene索引和查询

    Lucene最初是用Java编写的,因此在Java环境中使用非常方便。它提供了丰富的API,包括文档(Document)、字段(Field)、索引编写器(IndexWriter)、索引阅读器(IndexReader)、查询解析器(QueryParser)等类,...

    lucene索引查看程序及代码

    通过阅读和分析源代码,我们可以学习到如何操作Lucene索引,以及如何构建类似的工具。 总结而言,luke作为Lucene索引的可视化工具,极大地便利了开发者对索引的理解和调试。无论是初学者还是经验丰富的开发人员,都...

    Lucene5学习之增量索引(Zoie)

    Lucene本身并不直接支持增量索引,因此,开发者们开发了Zoie系统,它是基于Lucene的一个扩展,旨在解决大数据量场景下的实时索引问题。Zoie的名字来源于“Zero Indexing Overhead”,即零索引开销,它的核心思想是...

    lucene索引优化多线程多目录创建索引

    通过对“lucene_multiThreadIndex”压缩包的学习,你将掌握如何在Lucene中实现多线程索引,从而提高大型数据集的索引构建速度。通过实践,你可以更好地理解和应用这些技术,优化你的信息检索系统。

    lucene索引查看工具luck7.4.0

    在实际开发中,Luke是Lucene开发者的得力助手,它能帮助快速定位问题,验证索引构建是否正确,或者对搜索结果进行调试。使用Luke 7.4.0,你可以深入了解Lucene 7.x版本的索引结构和工作原理,从而提高你的搜索引擎...

    lucene 4.7.2 Demo

    在4.7.2这个版本中,Lucene已经对Java 6提供了全面的支持,而后续的版本则需要Java 7或更高版本的环境运行。本文将深入探讨Lucene 4.7.2的特性,包括创建、删除和修改索引,以及高级搜索功能如通用对象搜索、范围...

    Lucene3.0创建索引

    本篇文章将详细介绍如何使用Lucene3.0来创建索引,并通过一个具体的例子来演示整个过程。 #### 一、Lucene3.0简介 Lucene是一款高性能、全功能的全文搜索引擎库。它为开发者提供了构建搜索应用所需的所有基本工具...

    Lucene索引的基本操作

    本文将深入探讨Lucene索引的基本操作,包括如何添加文档到索引、更新已有的索引以及相关的测试代码。 ### 1. 初始化Lucene环境 首先,我们需要导入Lucene的相关库。在Java项目中,可以通过Maven或Gradle等构建工具...

Global site tag (gtag.js) - Google Analytics