在mongodb副本集的local库中,有一个replset.minvalid集合,这个集合正常情况下会记录一个OpTime,包含时间戳(ts)字段和选举任期(t,如果使用的v1选举协议)。有时候会有一些额外的字段,如『begin』、『doingInitialSync:true』等,如下,摘抄自mongodb代码注释:
* { _id:...,
* doingInitialSync: true // initial sync is active
* ts:..., t:... // end-OpTime
* begin: {ts:..., t:...} // a batch is currently being applied, and not consistent
* }
那这个集合是干什么用的呢?简单来说这个集合是Secondary节点用来标识当前是否处于一个一致状态。当节点已经应用到了这个集合中的OpTime对应的oplog,那么它是一致的。具体地看,这个集合主要有如下几个作用:
- 标记当前正在执行initial sync。在initial sync开始时,会在这个集合中写入一个『doingInitialSync:true』的标记,结束后清除。如果initial sync过程中进程crash了,下次重启的时候会根据这个标记重新进行initial sync。
- 保证Secondary节点在同步过程能原子性的应用一批oplog(即要么全部应用,要么全部不应用)。在Secondary节点同步的过程中,拉取了一批oplog后准备应用时,会在这个集合中写入这批oplog的时间戳区间。即将集合的OpTime更新成这批oplog的结束OpTime,另外再增加一个『begin』字段标识这批oplog的起始时间戳。当这一批oplog被成功应用完毕后,会将这个『begin』字段移除。如果在一批oplog应用途中进程crash了,下次重启时会通过『begin』字段检测到这是一次不完整的batch apply oplog操作,会将oplog截断到『begin』字段标识的OpTime之前,以将已应用的部分oplog删除掉。之所以要这么做是因为因为Secondary在apply一批oplog的时候是并发进行的,当中可能产生一些中间状态,需要保证全部apply完毕后才能对外可见。
- 如果Secondary节点在选择同步源的时候发现自己已经落后太多,已经跟不上其他节点,也会修改minvalid集合,将缺失的oplog时间区间(从自己的最新一条oplog的时间戳到看到的其他节点最旧的oplog时间戳)写到minvalid集合中,并进入维护模式,变为RECOVERING状态。从RECOVERING状态重新回到Secondary状态时也会检查是否已应用完了minvalid集合中记录的OpTime对应的oplog。
- 此外,当节点需要回滚(rollback)时,在回滚之前会获取minvalid集合的数据进行判断当前节点是否处于一致的状态,如果不是则直接assert结束进程。在回滚过程中,会在这个集合中记录当前同步源节点的最新的oplog的OpTime,以标识当前处于不一致状态,等到回滚结束后,由同步线程追上这个oplog后清除。回滚过程可参加MongoDB副本集回滚那些事