文档提交之flush(八)终

  本文承接文档提交之flush(七),继续依次介绍每一个流程点,本篇文章是介绍文档提交之flush流程的最后一篇文章。

文档提交之flush的整体流程图

图1:

更新ReaderPool

图2:

  在执行更新ReaderPool流程之前,我们需要等待所有发布生成的段中的处理删除信息事件执行结束。

  为什么需要等待

  等待的逻辑是什么

  为什么是至少主动flush必须(must be)要处理的删除信息都已经完成了,至少主动flush必须(must be)要处理的删除信息这句话需要拆分为两部分来介绍

  主动flush的线程如何获得当前update状态

更新ReaderPool的流程图

图3:

  ReaderPool是什么

  更新ReaderPool的过程就是更新每一个SegmentCommitInfo对应的ReadersAndUpdates的过程。

取出一个SegmentCommitInfo

图4:

  从IndexWriter的全局变量segmentInfos中依次取出每一个SegmentCommitInfo:

处理每一个SegmentCommitInfo

图5:

  文档提交之flush(七)中我们了解到全局FrozenBufferedUpdates中的删除信息会作用到segmentInfos中的每一个SegmentCommitInfo中,同时段内FrozenBufferedUpdates中的删除信息会作用到本段的SegmentCommitInfo,即当作用(apply)了删除信息后,每一个段中的删除信息可能会发生变化。如果一个段中有新的被标记为删除的文档产生,那么被删除的文档会被记录到.liv索引文件中,如果该段已经存在.liv索引文件,那么先生成一个新的.liv索引文件,然后删除旧的.liv索引文件(通过索引文件计数引用来判断是否能删除该索引文件,见文档提交之flush(七))。

  软删除也会使得对应的文档被标记为被删除的,故同时需要更新DocValues域,这部分在后面介绍软删除的文章中会展开介绍。

处理需要被丢弃的段

图6:

 

  在上面的流程中,通过.liv索引文件确定了每一个段中的被删除的文档集合,如果一个段中所有文档都被标记为删除的,那么需要丢弃该段。

  在执行完更新ReaderPool流程之后,Lucene还提供了一个钩子函数,用户可以根据具体业务来实现这个接口,这个接口同文档提交之flush(六)中的图3中执行flush后的工作流程是同一个钩子函数。

尝试段合并

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

结语

  至此,除了跟DocValues相关的知识点,我们通过八篇文章详细的介绍了执行了IndexWriter.flush()的所有流程。

  在后面的文章中,我们会介绍软删除的内容,填补未展开的坑。

点击下载附件