ReaderPool(一)(Lucene 8.7.0)

简介: ReaderPool(一)(Lucene 8.7.0)

ReaderPool(一)(Lucene 8.7.0)

  ReaderPool类对于理解Lucene的一些机制起到了极其关键的作用,这些机制至少包含段的合并、作用(apply)删除信息、NRT(near real-time)、flush/commit与merge的并发过程中的删除信息的处理等等,所以有必要单独用一篇文章来介绍这个类。下面先给出源码中对于这个类的介绍:

图1:

1.png

  图1的javadoc中这样描述ReaderPool类:该类持有一个或多个SegmentReader对象的引用,并且是shared SegmentReader,share描述的是在flush阶段、合并阶段、NRT等不同的场景中都共用ReaderPool对象中的SegmentReader。另外IndexWriter还会使用这些shared SegmentReaders来实现例如作用(apply)删除信息、执行段的合并NRT搜索

构造ReaderPool对象

  ReaderPool对象只在构造IndexWriter对象期间生成,正如图1中的Javadoc所描述的那样,它用来被IndexWriter使用。

图2:2.png

  我们通过ReaderPool的构造函数来介绍在构造ReaderPool对象期间一些主要的内容:

图3:

3.png

  我们看下图3中红框标注的部分内容,它描述的是通过参数StandardDirectoryReader reader,从中依次读取它包含的SegmentReader,然后将每个SegmentReader的信息存储到代码第93行的readerMap中。

构造函数的参数StandardDirectoryReader reader是哪里来的?

  通过图2的流程点获取IndexCommit对应的StandardDirectoryReader获得StandardDirectoryReader,在随后流程点生成对象ReaderPool中传递给ReaderPool的构造函数。

代码第93行的readerMap是什么?

  readerMap是一个map容器,它是ReaderPool对象的实例变量。其中key为SegmentCommitInfo对象,value为ReadersAndUpdates对象,如下所示:

图4:

4.png

  SegmentCommitInfo对象是什么?

  SegmentCommitInfo用来描述一个段元数据(metadata)。它是索引文件segments_N的字段:

图5:

5.png

  索引文件segments_N中用来保存描述每个段的信息的元数据SegmentCommitInfo。在图2的流程点获取IndexCommit对应的StandardDirectoryReader中通过读取索引目录中的索引文件segments_N获取每个段对应的SegmentCommitInfo,并且将它作为readerMap的key,用来区分不同的段。

  另外readerMap的value,即ReadersAndUpdates对象,它同样描述了段中的数据,下文中我们再对其展开介绍。

  故在构造ReaderPool的过程中,其最重要的过程就是记录当前索引目录中所有段的信息,在下文中,会介绍被记录的信息在什么情况下会被使用。

读取ReaderPool对象

  我们先看下readerMap中的value,即ReaderAndUpdates对象中包含了哪些内容:

图6:

6.png

  图6中红框标注的实例变量是我们关心的内容,我们一一介绍。

SegmentReader reader

图7:

7.png

  reader中包含的内容在文章SegmentReader(一)已经做了介绍,不赘述。

PendingDeletes pendingDeletes

图8:

8.png

  正如图8的注释描述的一样,pendingDeletes用来存储段中"新的"被删除的信息,注释中further deletions即"新的"被删除的信息。

  为什么要加黑突出"新的"这两个字?

  以在构造ReaderPool对象期间为例,图7中的SegmentReader中可能包含删除信息,这些删除信息是在图的流程点获取IndexCommit对应的StandardDirectoryReader通过读取索引目录中一个段对应的索引文件.liv获得的,我们称之为"旧的"删除信息。

  当后续索引(Indexing)过程中,如果存在删除操作,并且当前段满足这个删除条件,那么删除信息必须作用(apply)到这个段,这些删除信息称之为"新的"被删除信息,它们会被添加到pendingDeletes中,更准确的描述应该是这些"新的"删除信息被暂存到pendingDeletes。

  为什么是暂存"新的"的删除信息?

  如果不是暂存,那么就是持久化到磁盘,即生成新的索引文件.liv。但是每次有删除信息就执行I/O磁盘操作,这显然不是合理的设计。

  什么时候将"新的"删除信息持久化到磁盘?

  例如在执行flush、commit、获取NRT reader时。

图9:

9.png

  图9中,当用户调用了主动flush(执行IndexWriter.flush()操作),当执行到流程点更新ReaderPool,说明这次flush产生的"新的"删除都已经实现了apply,那么此时可以将"新的"删除信息生成新的索引文件.liv。

  什么时候一个段会被作用(apply)"新的"删除信息

  还是以图9的flush为例,在IndexWriter处理事件的流程中,会执行一个处理删除信息的事件,其流程图如下所示:

图10:

10.png

  图10中红框标注的两个流程点将会从段中找到满足删除条件的文档号,然后将删除信息暂存到pendingDeletes中。

  另外在执行段的合并过程中,待合并的段在图11的流程点作用(apply)删除信息被作用"新的"删除信息:

图11:

11.png

结语

  基于篇幅,剩余的内容将在下一篇文章中展开。

原文地址:https://www.amazingkoala.com.cn/

目录
相关文章
|
6月前
|
索引
lucene入门使用
lucene入门使用
39 2
|
Java 索引
04Lucene入门程序
04Lucene入门程序
53 0
|
存储 自然语言处理 算法
Lucene学习总结
Lucene学习总结
112 0
Lucene学习总结
|
分布式计算 算法 Hadoop
什么是 lucene|学习笔记
快速学习 什么是 lucene
什么是 lucene|学习笔记
|
调度 索引 容器
ReaderPool(二)(Lucene 8.7.0)
ReaderPool(二)(Lucene 8.7.0)
165 0
|
存储 自然语言处理 搜索推荐
MemoryIndex(一)(Lucene 8.8.0)
MemoryIndex(一)(Lucene 8.8.0)
592 0
MemoryIndex(一)(Lucene 8.8.0)
|
存储 自然语言处理 数据库
Lucene 查询原理
# 前言 Lucene 是一个基于 Java 的全文信息检索工具包,目前主流的搜索系统Elasticsearch和solr都是基于lucene的索引和搜索能力进行。想要理解搜索系统的实现原理,就需要深入lucene这一层,看看lucene是如何存储需要检索的数据,以及如何完成高效的数据检索。
8655 1
|
搜索推荐 Java Apache
Lucene7.2.1系列(二)luke使用及索引文档的基本操作
它有以下功能: - 查看文档并分析其内容(用于存储字段) - 在索引中搜索 - 执行索引维护:索引运行状况检查;索引优化(运行前需要备份) - 从hdfs读取索引 - 将索引或其部分导出为XML格式 - 测试定制的Lucene分析工具 - 创建自己的插件
2485 0
|
Java 索引 自然语言处理