本文承接近实时搜索NRT(四),继续依次介绍每一个流程点,阅读本文章需要看过文档的增删改、文档提交之flush的系列文章。
其中openIfChange的方法一&&方法二、方法三&&方法四的逻辑需要用图1、图2两个流程图展现:
图1:
点击查看大图
图2:
点击查看大图
图3:
如果oldReader是通过open方法(见近实时搜索NRT(一)、近实时搜索NRT(四))中的方法三或者方法四获得,那么oldReader就持有IndexWriter对象(见近实时搜索NRT(三)),当调用了openIfChange的方法一,该方法就会执行图3中的流程,这种方法属于NRT。
图3的流程描述了这么一个过程:根据oldReader中持有的IndexWriter判断索引是否发生变化,即流程点根据IndexWriter判断索引是否发生变化?
,发生变化则需要重新生成StandardDirectoryReader,如果生成了新的StandardDirectoryReader,那么需要再次跟oldReader作比较,即流程点新旧StandardDirectoryReader是否一致?
,如果不相同,那么返回这个新的StandardDirectoryReader,否则返回null。
根据IndexWriter判断索引是否发生变化需要判断下面四个条件,依次
同时满足视为没有发生变化:
条件一:oldReader与IndexWriter他们俩分别持有的SegmentInfos的版本号Version必须相同
获得所有段的信息集合SegmentInfos
的介绍条件二:目前没有正在处理的文档,该条件由四个子条件组成,所有子条件都满足视为满足条件二
子条件一:numDocsInRAM的值为0
子条件二:全局删除队列deleteQueue(见文档的增删改(下)(part 2))中的结点个数为0
子条件三:ticketQueue(见文档提交之flush(四))中的元素个数为0
子条件四:pendingChangesInCurrentFullFlush的值为false
条件三:所有的删除信息都已经作用到其他的段
发布生成的段
的流程,该流程中从ticketQueue中依次取出FlushTicket,随后执行的两个工作分别是将删除信息作用到其他的段和将DocValues更改信息作用到其他的段,只有这个两个工作完成了,才能保证段的信息不会再被改变,否则段可能会被改变,那么oldReader需要更新条件四:所有的DocValues更改信息已经作用到其他的段
需要满足条件二、条件三、条件四正是说明了我们重新获得StandardDirectoryReader中包含了未提交(commit操作)的索引信息,所以这种方法属于NRT(见近实时搜索NRT(一)文章中对NRT的定义)。
为什么需要同时满足上面的四个条件(重要):
依次
同时满足,并且判断版本号是第一个判断条件生成了新的StandardDirectoryReader后,为什么还要跟oldReader比较是否一致(相同):
新旧StandardDirectoryReader是否一致?
的流程点,它的判断方法是通过比较新旧两个StandardDirectoryReader他们分别持有的segmentInfos的版本号Version是否一致 为什么已经在流程点根据IndexWriter判断索引是否发生变化?
已经判断出索引信息发生变化,还会出现新的StandardDirectoryReader跟oldReader包含相同的索引信息(重要):
至此我们介绍完了图1中的所有流程,由于图2中的流程点与图1中的流程点是重复的,所以不对图2的流程展开介绍,那么Lucene提供的性能更高获得StandardDirectoryReader对象的openIfChange()方法就都介绍结束了。
在下一篇文章中,我们将会继续DirectoryReader的其他子类(见近实时搜索NRT(一)的图1)。
点击下载附件