本文承接文档提交之flush(五),继续依次介绍每一个流程点。
图1:
强制发布生成的段
图2:
在文档提交之flush(五)中我们还剩余发布FlushedSegment
跟发布FlushedSegment
两个流程点未介绍。
发布FlushedSegment
的流程图 图3的流程图描述的是一个FlushTicket执行发布FlushedSegment
流程所涉及的处理过程。
图3:
图4:
首先给出FlushTicket类,类中包含的主要变量如下:
xxxxxxxxxx
static final class FlushTicket {
private final FrozenBufferedUpdates frozenUpdates;
private FlushedSegment segment;
... ....
}
从前面的文章(见文档提交之flush(二))中我们了解到,不是每一个FlushTicket都有全局删除信息,即FrozenBufferedUpdates可能为null。如果不为空,我们首先要获得一个nextGen。
nextGen有什么作用:
由于根据nextGen能保证正确的处理删除信息,所以真正的从别的段中处理删除信息的操作,即处理删除信息
,就可以作为一个事件添加到eventQueue(见文档提交之flush(四)),使得可以多线程并发执行,在下篇文章中我们将会了解到,处理删除信息
的过程是开销较大的工作。
图5:
在文档提交之flush(四)中我们简单介绍了FlushTicket 中的FlushedSegment中包含的几个信息,至少包含了一个DWPT处理的文档对应的索引信息(SegmentCommitInfo)、段中被删除的文档信息(FixedBitSet对象)、未处理的删除信息FrozenBufferedUpdates(见文档提交之flush(三))、Sorter.DocMap对象,以上内容在文档提交之flush(三)的文章中已介绍。在当前流程点,FlushedSegment中的FrozenBufferedUpdates(非FlushTicket中的FrozenBufferedUpdates)中包含了段内的删除信息。
另外,在文档提交之flush(三)中我们介绍了,在生成索引文件的过程中,我们只处理了部分满足删除信息(见下文处理丢弃的段
的介绍)的文档,到此流程点,我们需要处理剩余的删除信息。
无论当前FlushTicket中是否还有段内删除信息,当前段都需要获得一个nextGen,之后任何大于nextGen值的删除信息都需要作用到当前段。
图6:
将FlushedSegment中的SegmentCommitInfo,即索引信息添加到SegmentInfos中。SegmentInfos即所有段的索引信息的集合, 在commit( )阶段,SegmentInfos中的信息对应生成Segment_N的索引文件。
图7:
如果当前段中的文档的总个数maxDoc与被标记为删除的(deleted)文档的个数相同,那么该段需要被丢弃,判断条件如下:
xxxxxxxxxx
delCount + softDelCount == maxDoc
处理软删除文档
的流程中,计算出了softDelCount的值,不赘述从上文介绍中我们知道,当前段的SegmentCommitInfo已经被添加到SegmentInfos中,由于段的合并跟flush是异步操作,故运行到此流程点时,当前段可能正在执行段的合并。如果正在合并当前段,那么就不处理,在合并结束后,会自动丢弃该段,否则将此段对应SegmentCommitInfo从SegmentInfos中移除。
图8:
同图1中的执行flush前的工作
的流程点,Lucene在此流程点预留了一个钩子函数(hook function),使用者可以实现在此实现自己的方法。
至此,强制发布生成的段
中的发布FlushedSegment
流程介绍结束,另外发布FrozenBufferedUpdates
的流程逻辑即上文中的处理全局删除信息
。
在执行该流程之前,需要先执行下面的几个收尾工作,即执行源码中DocumentsWriterFlushControl.finishFullFlush( )的方法:
执行DWPT的doFlush()
的流程,注意的是当前线程还未释放用来同步主动flush的fullFlushLock对象(见文档提交之flush(一))上面的收尾工作结束后,接着还需要尝试处理newQueue中的删除信息。
为什么此时需要尝试处理newQueue中的删除信息:
执行DWPT的doFlush()
流程中已经处理过一次newQueue中的删除信息,条件是内存中的删除信息如果超过阈值的一半,那么需要处理删除信息,阈值即通过IndexWriterConfig setRAMBufferSizeMB设置允许缓存在内存的索引量(包括删除信息)的最大值,目的是为了防止产生过多的小段。为什么此时能尝试处理newQueue中的删除信息:
执行完收尾工作后,当前线程从eventQueue队列中逐个取出所有的事件,即执行事件对应的函数调用,关于事件的概念见文档提交之flush(四)。
总结前几篇文章中的内容,eventQueue中包含以下几种事件类型:
在下篇文章中,将会介绍图1中剩下的几个流程点以及发布生成的段中
生成的处理删除信息
事件的逻辑。
点击下载附件