html中设置提交执行,文档提交之commit(二)

本篇文章承接文档提交之commit(一),继续介绍文档提交之commit的剩余流程点。

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

图1:

7d86e00d194fe51e74d02e6890b8f41c.png

点击查看大图

生成新的Segment_N文件

图2:

99bf3e4fdea8f0db56688b36e316f352.png

在文档提交之commit(一)中,我们介绍了图1的执行同步磁盘工作的流程点,在这个流程点中,最重要的一个任务是保证所有的索引文件被持久化到磁盘上,另外还需要生成一个pending_segments_N文件,其中N描述了当前索引目录中索引文件的被提交的最新的一个迭代数(generation),这是一个从数值1开始递增的值,例如我们第一次执行两阶段提交之第一阶段后,会生成pending_segments_1,第二次执行两阶段提交之第一阶段后,会生成pending_segments_2,以此类推,由于图1的两个同步机制,使得N在临界区内递增,所以更新并获得N值的实现很简单:xxxxxxxxxx

private long getNextPendingGeneration() {// generation == -1 说明是第一次执行两阶段提交之第一阶段if (generation == -1) {return 1;} else {return generation+1;}

pending_segments_N文件是什么:pending_segments_N就是segments_N文件,在当前流程点生成新的Segment_N文件只是简单的将pending_segments_N重命名为segments_N,最后再次同步磁盘,保证重命名正确被执行

执行检查点(checkPoint)工作

在这个流程中,顺序执行以下的操作:操作一:增加这次提交对应的索引文件的计数引用(计数引用的概念见文档提交之commit(一))

操作二:执行索引删除策略(IndexDeletionPolicy)

操作三:减少被删除的提交对应的索引文件的计数引用

操作二:执行索引删除策略(IndexDeletionPolicy)

为了便于理解,我们先介绍操作二:执行索引删除策略(IndexDeletionPolicy) 。

IndexDeletionPolicy描述了当新的提交发生后,如何处理旧的提交,下图给出了Lucene7.5.0中核心包core中的IndexDeletionPolicy类的类图:

图3:

59a713053c09c1befb2b9d015dbfeb03.png

NoDeletionPolicy

该策略描述了无论有多少次新的提交,旧的提交都不会被删除,下图展示了执行5次IndexWriter.commit()方法后索引目录中部分文件:

图4:

266e8d21bf7b309b63272967a4503ed6.png

使用这种索引删除策略的优点在于,配合segments_N文件和commitUserData(见文档提交之commit(一))我们可以将索引信息恢复到任意一个提交状态;缺点在于索引目录需要保留大量的索引文件,特别是多线程下执行flush()操作较多的场景下,如果你看过文档的增删改的系列文章,索引文件的数量与DPWT对象的个数成正比。

KeepOnlyLastCommitDeletionPolicy

该策略是Lucene7.5.0中默认的策略,它描述了当有新的提交,则删除上一个提交,即索引目录中最多只存在一个segment_N文件。

SnapshotDeletionPolicy

SnapshotDeletionPolicy用来保留提交的快照,它封装了其他的索引删除策略,由于NoDeletionPolicy保留了每一次的提交,所以封装该策略没有什么意义,当封装了KeepOnlyLastCommitDeletionPolicy,那么可以通过主动调用SnapshotDeletionPolicy.snapshot()的方法来实现快照功能,使得新的提交产生后,上一个提交能以快照的方式保留在内存中,这种策略的缺点在于需要额外一份索引信息大小的内存。

PersistentSnapshotDeletionPolicy

该策略跟SnapshotDeletionPolicy一样提供快照功能,区别在于SnapshotDeletionPolicy的快照信息保留在内存中,而该策略则持久化(persist)到磁盘,并且生成snapshot_N文件,该文件中描述了快照信息,不展开介绍:

图5:

28912956603b33bfa515e44649f3bbd6.png

另外SnapshotDeletionPolicy跟PersistentSnapshotDeletionPolicy都可以设置多个快照,只需要在每次提交后,执行SnapshotDeletionPolicy.snapshot()方法即可。

使用了封装KeepOnlyLastCommitDeletionPolicy的SnapshotDeletionPolicy或者PersistentSnapshotDeletionPolicy策略,控制了KeepOnlyLastCommitDeletionPolicy处理上一个提交的方式,上文中我们说到,每当一个新的提交产生,根据KeepOnlyLastCommitDeletionPolicy,旧的提交就会删除,即引目录中最多只存在一个segment_N文件文件,通过封装后,在每次执行IndexWriter.commit()后,主动调用了SnapshotDeletionPolicy.snapshot()的方法后,能使得上一个提交不再被删除,即保留旧的segment_N文件,这既是快照的实现本质。

例子1

图6中,我们只使用KeepOnlyLastCommitDeletionPolicy策略,并且执行三次commit()操作:

图6:

cad8011f29325a740b6299b64a7b3c8e.png

图7为图6中执行了三次commit()操作后索引目录中segment_N文件,由于使用了KeepOnlyLastCommitDeletionPolicy策略,故segment_1、segment_2文件分别被删除,只留下segments_3:

图7:

3166ecc4380645c96cd958055c01fb7d.png例子2

图6中,我们使用了封装KeepOnlyLastCommitDeletionPolicy的PersistentSnapshotDeletionPolicy策略,并且执行三次commit()操作,并且当count == 2时不生成快照,也就是不对segment_2生成快照:

图8:

d58d63f85e78529ba903fd31a6812731.png

图9为图8中执行了三次commit()操作后索引目录中segment_N文件,由于使用了PersistentSnapshotDeletionPolicy策略,故只有segment_2被删除,留下segments_1跟segments_3:

图9:

f56030a325d64ecdb0e96786de7fa3b7.png

通过上面的例子我们可以看出以下的内容:可以选择性的执行快照功能:图8中我们没有对segments_2执行快照功能

快照功能的实现方式:通过保留segment_N文件的方式

最后,对于PersistentSnapshotDeletionPolicy策略,生成跟删除快照都有磁盘同步操作(见文档提交之commit(一)关于同步磁盘的介绍),这是需要注意的地方。

操作一:增加这次提交对应的索引文件的计数引用

在操作二中,我们了解到,有些索引删除策略会删除上一个提交,删除提交的过程实质是减少该提交对应的索引文件的计数引用,为了防止本次提交对应的索引文件被误删,所以需要增加这次提交对应的索引文件的计数引用。

在文档提交之commit(一)中,我们已经增加了新的提交对应的索引文件的计数引用(图1中,二阶段提交之第一阶段的更新索引文件的计数引用),为什么这里还要增加:二阶段提交之第一阶段的更新索引文件的计数引用目的是防止执行段合并的其他线程导致索引文件被删除,操作一中的更新操作对应的是操作二中的情况,两次的更新操作目的不一样。

操作三:减少被删除的提交对应的索引文件的计数引用

基于索引删除策略,当旧的提交被删除后,通过减少其对应的索引文件的计数引用来正确删除索引目录中的部分索引文件。

设置rollbackSegments

图10:

277026c223d32f7aa3d2034eeb0995cd.png

这里对本次提交对应的索引信息进行备份,使得可以实现回滚操作,该操作在后面的文章中会介绍,rollbackSegments的定义如下xxxxxxxxxx

private List rollbackSegments;

该流程将pendingCommit(见文档提交之commit(一))中最重要的信息备份到rollbackSegments中。

更新索引文件的计数引用

图11:

7f0afb67f47142cfa9fef25c65b1d022.png

从图1中的流程中我们知道,本次提交对应的索引文件一共增加了两次计数引用,到此流程点时,我们已经完成了commit的工作,故需要减少本次提交对应的索引文件的计数引用。

另外释放对象锁,使得其他线程可以执行commit()的操作,至此二阶段提交之第二阶段的流程都已完成。

尝试段合并

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

结语

至此我们介绍完了文档提交之commit的整体流程图,由于最复杂的部分跟flush()操作是一样的,所以相比较文档提交之flush的8篇系列文章,只用2篇文档就搞定了。在下一篇文章中,将会介绍commit()跟flush()的区别,这也是面试官经常会问的内容。

点击下载附件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值