近实时搜索NRT(三)

  近实时搜索NRT(二)的文章中我们提到,Lucene提供了四种方法来获得StandardDirectoryReader对象,这里先简单总结下这四种open方法获取StandardDirectoryReader的差异:

  近实时搜索NRT(一)近实时搜索NRT(二)中我们了解到,无论调用哪一个上述介绍的方法,其相同的逻辑都是将一个段的信息segmentCommitInfo封装为一个LeafReader,最后将多个LeafReader封装为StandardDirectoryReader,当索引目录中的索引信息发生更改时,我们可以通过重新调用上述的方法来获得最新的StandardDirectoryReader,但是基于下面的几个考虑,Lucene提供了性能更高的openIfChanged方法来获得最新的StandardDirectoryReader:

  Lucene7.5.0中提供了以下四种openIfChange方法,这四种方法:

openIfChange方法的流程图

  其中openIfChange的方法一&&方法二、方法三&&方法四的逻辑需要用两个流程图图1、图2展现:

图1:

点击查看大图

图2:

点击查看大图

  在介绍每一个流程点之前,我们先大致先说下图1、图2的流程,两个流程图总体描述了旧的StandardDirectoryReader,即oldReader(DirectoryReader的子类,见近实时搜索NRT(一))在经过一系列的流程后,判断是否需要生成新的StandardDirectoryReader,如果不需要那么返回null,否则生成一个新的StandardDirectoryReader,生成的新的StandardDirectoryReader的方法有两个,即图1、图2中用红色紫色标注的两个流程点,而这两种获取新的StandardDirectoryReader的方法即近实时搜索NRT(一)近实时搜索NRT(二)介绍的四种open方法,如下图所示:

图3:

点击查看大图

  下面我们先介绍图1中的每一个流程点。

IndexWriter是否为空?

图4:

  IndexWriter是否为空描述的是旧的StandardDirectoryReader,即oldReader中是否持有IndexWriter对象的引用。

  如何判断oldReader中是否持有IndexWriter对象的引用:

根据Directory判断索引是否发生变化?

图5:

  如果oldReader是通过open方法中的方法一或者方法二获得的,并且调用openIfChange的方法一,由于该方法没有indexCommit参数,故该方法会执行图5中的流程。

  方法一只提供了一个oldReader的参数,并且没有持有IndexWriter对象的引用,所以判断是否需要获取新的StandardDirectoryReader的方式为根据索引目录中最后一次commit,对比最后一次commit对应的SegmentInfos对象跟oldReader中的SegmentInfos的版本号Version是否一致,如果不一致,说明索引信息在生成oldReader之后发生了变化,那么我们需要重新生成一个新的StandardDirectoryReader,否则返回null。

  SegmentInfos是什么

  SegmentInfos的版本号Version是什么

  段的什么变化会引起版本号Version的变化

图6:

  图6中,红框标注的为某次提交对应的SegmentInfos的版本号。

  如何根据最后一次commit获得SegmentInfos

  图5中如果根据Directory判断索引发生了变化,那么通过图3的流程获得一个新的StandardDirectoryReader。

  如何获得新的StandardDirectoryReader

segment_N文件是否一致?

图7:

  如果oldReader是通过open方法中的方法一或者方法二获得的,并且调用openIfChange的方法二,由于该方法有indexCommit,那么该方法会执行图7中的流程。

  方法二描述的是根据参数IndexCommit来获得对应的StandardDirectoryReader,另外通过比较oldReader中对应的segment_N文件名是否跟方法二的参数IndexCommit中的segment_N文件名是否相同来判断是否需要获得新的StandardDirectoryReader。

  如何通过oldReader获得对应的segment_N文件

  lastGeneration什么时候被赋值的:

  另外IndexCommit类中有一个变量叫做segmentsFileName,该变量用来保存segment_N的文件名。

  当判断出segment_N的文件名不一致,那么我们需要重新获得StandardDirectoryReader,即图7中的找出变更的LeafReader流程点,同样的,详细的获得过程在下一篇文章中展开。

结语

  基于篇幅,剩余的流程点将在下一篇文章中展开。

点击下载附件