在前面的文章中,我们介绍了段的合并策略TieredMergePolicy、LogMergePolicy,讲述了如何从索引目录中挑选出满足合并条件的一个或多个段的集合OneMerge,另外还介绍了段的合并调度MergeScheduler,讲述了如何用不同的调度策略分配一个或多个线程来调度段的合并,比如执行先后顺序,磁盘IO限制。
图1是文章MergeScheduler中的调度策略ConcurrentMergeScheduler的流程图,其中红色框标注的流程点描述的是一个线程执行段的合并的过程,然而基于篇幅我们并没有展开介绍,故从本篇文章开始,将通过数篇文章来介绍该流程点的逻辑:
为了能更好的理解图1中每一个流程点,强烈建议先看下文档提交之flush系列文章。
图1:
图2:
点击查看大图
我们首先概述下图2中三个阶段:
接下来我们介绍图2中的每一个流程点
该流程点即流程图的输入数据,该数据为OneMerge,它描述了待合并的段的信息,包含的几个重要的信息如下所示:
图3:
SegmentCommitInfo的信息由图3中黄框标注的两部分组成,其中根据索引文件segments_N中红框标注的SegName(见文章索引文件segments_N)找到对应的索引文件si。
图3中两个索引文件中的字段已经在前面的文章中介绍,在这里不赘述。
在文档提交之flush(二)中我们提到,DWPT(见文档的增删改(中))转化为一个段的期间,DWPT中包含的删除信息会被处理为两种BufferedUpdates(不用关心BufferedUpdates具体包含哪些信息),如下所示:
由于段的合并操作会合并掉删除信息,故我们必须在合并之前将待合并的段包含的删除的信息正确的作用到其他段以及自身段。
作用(apply)删除信息的具体过程可以查看文档提交之flush(七)中的处理删除信息的流程图
,本文就不赘述了。
为什么我们已经能获得待合并段的信息,但段中的删除信息在这个流程点可能还未作用删除信息?
子问题一:执行合并的操作时,我们是如何获得待合并段的信息:
private List<SegmentCommitInfo> segments = new ArrayList<>();
发布FlushedSegment的流程图
中,详细的介绍了一个段的信息SegmentCommitInfo被添加到链表segments的时机点,下图中用红色框标注:图4:
子问题二:为什么段中的删除信息在这个流程点可能还未作用删除信息:
事件
添加到eventQueue中,等待线程去执行eventQueue中的事件,即并不是马上作用(apply)删除信息,故当我们从链表segments 中得到待合并的段后,并不意味保证作用删除信息了,为了防止合并后删除信息的丢失,需要先作用删除信息这个流程点的过程相对复杂,基于篇幅,我们将在下一篇文档中展开。
由于执行段的合并跟文档的增删改,文档提交(commit、flush)是并发的操作,所以在介绍执行段的合并过程中肯定会有同步操作,也就是会把文档的增删改,文档提交(commit、flush)的知识点串起来讲解,故如果你不熟悉这些两个知识点,不是很适合看执行段的合并的系列文章。。。
点击下载附件