近实时搜索NRT(二)

  本文承接近实时搜索NRT(一),继续依次介绍每一个流程点。

获取StandardDirectoryReader对象的流程图

图1:

点击查看大图

  我们继续介绍方法三&&方法四的所有流程点。

  这两种是业务中最常使用,通过IndexWriter实现NRT功能的方法,在构造IndexWriter对象期间,会读取Directory,即索引目录中的已存在的索引信息(旧的索引信息),而对索引信息的更改(新的索引信息)都需要通过IndexWriter对象,故通过IndexWriter对象,我们能获得Directory中新旧索引信息,实现NRT。

  我们将方法三&&方法四的流程从图1中拆解出来,并且跟文档提交之flush(一)的流程进行对比,如下图所示:

图2:

点击查看大图

  图2中两个流程图中用红色标注的描述了他们具有具有相同的流程。

  为什么获取StandardDirectoryReader需要执行flush的操作

  为什么执行更改索引信息操作之后,其变更的内容并不马上生成新段或更新旧段

获得StandardDirectoryReader

图3:

  在图2中红色标注的流程执行结束后,新旧索引信息都生成了SegmentCommitInfo,那么我们就可以获得StandardDirectoryReader了,其获得过程跟方法一&&方法二的获得StandardDirectoryReader是一致的,不赘述。

执行flush后的工作

图4:

  该流程在前面的文章已经介绍,在源码中调用DocumentsWriterFlushControl.finishFullFlush( )的方法,详细的介绍见文档提交之flush(六)文章中的IndexWriter处理事件章节的内容。

执行获得reader后的工作

图5:

  Lucene在当前流程点提供一个钩子函数doAfterFlush()方法,用户可以实现自己的业务逻辑,定义如下:

尝试段合并

图6:

 

  由于执行了flush的操作,故索引可能发生了变化,在每一次索引发生变化后,都需要尝试判断是否需要执行段的合并操作,其判断条件依据不同的合并策略而有所不同,合并策略的文章可以看这里:LogMergePolicyTieredMergePolicy

结语

  我们通过调用图1中的四个方法来获得索引目录中最新的索引信息,无论哪一种方法,目的就是将索引目录中每一个段的信息生成一个LeafReader,最后将LeafReader封装为StandardDirectoryReader,然而这四种方法还存在性能问题,故Lucene提供了openIfChange的方法来提高NRT的性能,具体内容将在下篇文章中展开介绍。

点击下载附件