构造对象十
本文承接 构造 IndexWriter 对象(九),继续介绍调用 IndexWriter 的构造函数的流程。
调用 IndexWriter 的构造函数的流程图
图 1:
生成对象 IndexFileDeleter
我们紧接上一篇文章,继续介绍剩余的流程点,下面先给出 IndexFileDeleter 的构造函数流程图:
IndexFileDeleter 的构造函数流程图
图 2:
执行检查点(checkPoint)工作
在上一篇文章中,我们简单提了一下该流程点,其中 checkPoint 的作用及其逻辑在文章 构造 IndexWriter 对象(八) 已经介绍,不赘述,我们关注问题是为什么在当前流程点还要执行 checkPoint 的工作,这也是上一篇文章遗留的问题。
为什么这里还要执行一次 checkPoint 的工作:
先给出源码中的注释:
Always protect the incoming segmentInfos since sometime it may not be the most recent commit 上述注释中的 segmentInfos 即图 2 流程图中的准备数据 SegmentInfos
,该段注释展开后的具体内容描述的是如果最后一次 commit(索引目录 segments_N 中 N 值最大的那次提交)中不包含该 SegmentInfos 信息,那么为了防止 SegmentInfos 对应的索引信息因为某些索引删除策略 IndexDeletionPolicy 被删除,故需要执行 checkPoint 的工作。
我们以一个例子来描述对应的场景,该例子中的 oldIndexWriter 使用的索引删除策略是 NoDeletionPolicy,完整 demo 见: https://github.com/LuXugang/Lucene-7.5.0/blob/master/LuceneDemo/src/main/java/lucene/index/PersistentSnapshotDeletionPolicyTest.java 。
图 3:
图 3 中,在执行了第 56 行以及第 62 行的代码的 oldIndexWriter.commit()方法后,索引目录中生成了两个段,如下所示:
图 4:
接着在执行了第 63 行的代码后,我们通过索引删除策略 PersistentSnapshotDeletionPolicy 对索引目录中最新的一次提交生成一个快照,该提交即 segments_2,并通过 PersistentSnapshotDeletionPolicy.snapshot() 方法获得一个 IndexCommit 对象,并且在第 75 行我们将这个 IndexCommit 对象作为构造 newIndexWriter 的配置,此时索引目录中的内容如下所示:
图 5:
图 5 中 snapshots_0 即生成的快照。
IndexCommit 对象中的索引信息即快照对应的索引信息,即 segments_2 对应的索引信息,对应的索引文件即_0.cfe、_0.cfs、_0.si、_1.cfe、_1.cfs、_1.si,如下图所示:
图 6:
图 6 中,根据 SegmentCommitInfo 的 SegName 字段获得对应的 索引文件。si。
我们顺便给出 segments_1 包含的索引信息,在后面的流程中会用到:
图 7:
接着在执行了第 70 行的删除文档操作后,由于文档 0 跟文档 1 都满足该删除条件,即文档 0 跟文档 1 中都包含域名为"author",域值为"Lucy"的信息,那么在执行了第 71 行的 oldIndexWriter.commit()后,生成的第三个段中就不会包含文档 1 以及文档 2 的信息,即不会包含以_0 为前缀和以_1 为前缀的段的信息,索引目录中的内容如下所示:
图 8:
segments_3 包含的索引信息如下所示:
图 9:
图 9 中以_2 为前缀的段的索引信息即在图 3 中文档 2 对应的内容。
接着执行图 3 中第 77 行代码构造 newIndexWriter,执行完下图中标注的流程后,会根据索引目录中的 segments_N 文件对其对应的索引文件执行计数 +1 的操作:
图 10:
根据图 8 的索引目录中的内容,有 segments_1、segments_2、segments_3 共三个 segments_N 文件,他们对应的索引文件的计数如下所示:
表 1:
段名/索引文件_0.cfs_0.cfe_0.si_1.cfs_1.cfe_1.si_2.cfs_2.cfe_2.sisegments_1111000000segments_2111111000segments_3000000111计数和值222111111
根据图 6、图 7、图 9,每个 segments_N 文件对应的索引文件计数和如上所示,它描述了这些索引文件被引用的次数,故称为计数引用。
在继续介绍之前,我们先介绍下图 10 中标注的流程点 执行CommitPoint的删除工作
:
- 根据索引删除策略,那些应该被删除的提交在标注的流程点
执行索引删除策略
执行结束后,这些提交只是被添加到 待删除队列 中,并没有正在被删除,真正的删除工作是在流程点执行CommitPoint的删除工作
完成的
如何执行删除工作:
其过程就是对所有待删除的提交对应的索引文件执行计数-1 的操作,如果计数值为 0,那么索引文件就会被删除。
我们回到图 3 的例子,当执行到图 10 中的标注的 流程时
,如果图 3 中的 newIndexWriter 使用的是 KeepOnlyLastCommitDeletionPolicy,该索引删除策略描述的是只保留最新的提交,即只保留 segments_3 对应的索引信息,segments_1 跟 segments_2 对应的索引信息都需要被删除,故这两个段在流程点 执行索引删除策略
中被添加到 待删除 队列, 如果不执行 执行检查点(checkPoint)工作
,而是直接执行标注的流程点,那么根据表 1 中的内容,索引文件_1.cfs、_1.cfe、_1.si 由于在执行计数-1 的操作后,计数值都变为 0 而被删除,但由于构造当前 newIndexWriter 对象使用了 IndexCommit(快照 snapshot 的索引信息)配置,该对象对应的索引信息是 segments_2,而 segments_2 中包含索引文件_1.cfs、_1.cfe、_1.si 的索引信息,如果被删除,那么索引信息就会被破坏,所以我们必须在 执行CommitPoint的删除工作
之前先执行 执行检查点(checkPoint)
来增加 segments_2 对应的索引文件的计数值,而这就是注释所谓的"Always protect the incoming segmentInfos since sometime it may not be the most recent commit"。
在执行完 执行检查点(checkPoint)工作
工作后,索引文�
- 原文作者:知识铺
- 原文链接:https://index.zshipu.com/geek/post/%E4%BA%92%E8%81%94%E7%BD%91/%E6%9E%84%E9%80%A0%E5%AF%B9%E8%B1%A1%E5%8D%81/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
- 免责声明:本页面内容均来源于站内编辑发布,部分信息来源互联网,并不意味着本站赞同其观点或者证实其内容的真实性,如涉及版权等问题,请立即联系客服进行更改或删除,保证您的合法权益。转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 sblig@126.com