回滚(rollback)操作是MongoDB副本集产生一些反常主备切换后或许产生的现象。回滚操作会吊销在当时节点上已履行的一些修正操作。
什么时分会触发回滚
MongoDB副本集节点上有个同步线程,担任拉取需求同步的oplog。被拉取oplog的节点称作同步源。那么,要回滚,首要要有一个同步源。
同步源
链式仿制
平常咱们都说主备同步主备同步,那同步源肯定是主节点了?其实不一定,MongoDB很早就支撑了链式仿制,即备节点能够从别的一个备节点拉取oplog,而不只从主节点拉取。这样一来能够削减主节点的负载,二来各节点能够挑选离自己近的节点进行同步。当然,在某些状况下,这或许会导致一些备节点的推迟变大。链式仿制能够经过以下指令来翻开或封闭:
cfg = rs.config()
cfg.settings.chainingAllowed = true/false
rs.reconfig(cfg)
Secondary节点怎样挑选同步源
Secondary节点会依据以下准则挑选一个同步源:
假如之前有经过指令replSetSyncFrom指定了同步源,那么运用此同步源
因为后续需求依据到其他节点的ping值(经过心跳进行核算)信息进行挑选,这儿会判别一下是否已有满足的信息,需求等候更多的心跳包,假如不需求,持续,不然直接回来,等下次需求挑选时再看
假如没有敞开Chained Replication(链式仿制),那么挑选Primary
经过两轮挑选,依据以下规矩挑选一个ping值最低的节点:
假如自己能够建索引,那么只能从相同能够建索引的节点同步
oplog的时刻戳比我新(这儿是获取该节点前次心跳包里带的appliedOpTime的时刻戳进行比较)
不在黑名单中(注:何时将同步节点加进黑名单?1. 衔接不上该节点,加10s黑名单;2. 落后该节点太多无法持续同步,加1min黑名单)
其间在第一轮挑选中,会额定考虑以下条件:
1. 具有投票权的节点只能从相同具有投票权的节点同步
2. 不能从hidden节点同步
3. 不能从落后Primary太多(超越装备的maxSyncSourceLagSecs)的节点同步
4. 不能从装备了比自己具有更大delay的节点同步
假如第一轮没有选出适宜的节点,那么再进行第二轮挑选,放宽上述条件的约束。
什么时分会触发回滚(续)
回到回滚触发条件。同步线程现已挑选出了一个同步源,它向同步源建议一个find恳求,查询大于等于其最新的oplog时刻戳的oplog。假如产生以下两种状况,那么需求回滚:
1. 在同步源上没有查到比其更新的oplog(咱们刚刚经过一系列费事的规矩选出它作为同步源,可是咱们的oplog却比它还新)
2. 回来的的第一条oplog和其最新的oplog的OpTime和hash都不同,留意这儿是比较整个OpTime,即除了时刻戳之外还包括term,首要会比较term,假如term不同,那就不同
回滚详细流程
回滚之前会获取minvalid调集的数据进行判别当时节点是否处于共同的状况,假如不是则直接assert完毕进程。关于minvalid调集的作用,可拜见MongoDB中local.replset.minvalid调集的作用。假如答应进行回滚,则履行以下过程:
记载日志『rollback 0』
进入ROLLBACK状况
记载日志『rollback 1』
向同步源发送一个replSetGetRBID的指令获取一个rollbackId,这个rollbackId是用来在后面判别在rollback过程中同步源本身是否产生回滚,每个节点假如产生rollback,会修正自己的rollbackId。
记载日志『rollback 2 FindCommonPoint』
查找自己和同步源的oplog的commonPoint,这儿是从同步源最新的oplog开端逆向查找,比较自己和同步源的最新的oplog的时刻,核算相差的秒数,假如超越30分钟,那么抛弃rollback;假如本地的oplog时刻戳比对方的更新,往前持续找,直到找到时刻戳持平的那条。这儿每比较一条本地的oplog,都会对oplog的内容进行解析,然后得到回滚所需履行的操作集(包括需求从头从同步源获取的文档、需求从头同步的调集、需求drop的调集、索引等。这儿一起也会进行一些判别,假如有发现某条oplog的巨细大于512MB,抛弃回滚。假如有dropDatabase操作,抛弃回滚。)。找到了时刻戳持平且hash共同的oplog,就找到了commonPoint。
记载日志『rollback 3 fixup』
自增rollbackId
接下来依据刚刚解析oplog得到的需求从头从同步源获取其最新版别的文档集,从同步源逐一获取,并保存在一个map中。这儿会对要回滚的数据总巨细进行判别,不能超越300MB。一切文档处理完毕后,从同步源获取其最新的oplog的时刻备用
记载日志『rollback 3.5』
再次获取同步源的rollbackId,假如和刚刚得到的不一样,那阐明同步源本身也产生了回滚,抛弃这次回滚操作
记载日志『rollback 4 n:需求更新的文档个数』
将方才第9步从同步源得到的最新的oplog的时刻戳作为完毕时刻,刺进一个时刻戳区间到minvalid调集,标明当时数据处于不共同状况。
假如有需求从头同步整个调集数据或元数据的的,逐一处理(从头同步调集数据的,先drop然后copyCollection;从头同步调集元数据的,获取元数据并更新到本地),此处会记载日志『rollback 4.1.1 coll resync』或『rollback 4.1.2 coll metadata resync』。这儿因为或许比较费时,记载日志『rollback 4.2』,然后再一次获取同步源最新的oplog时刻戳记载到minvalid调集,并再次判别同步源是否本身产生回滚。假如一切正常,记载日志『rollback 4.3』。
记载日志『rollback 4.6』
处理需求drop的调集(假如有),这儿会做collScan即将drop的调集的文档的内容写到rollback目录里的文件中
处理需求drop的索引(假如有)
记载日志『rollback 4.7』
处理刚刚从同步源获取的最新版别的文档集,先将本地的文档写到rollback目录里的文件中,然后删去或更新
记载日志『rollback 5 d:删去的文档数 u:更新的文档数』
记载日志『rollback 6』
铲除本地oplog调集中在commonPoint之后的oplog
reload本地的最新oplog
记载日志『rollback done』
再次自增自己的rollbackId
记载日志『rollback finished』
3.2.11曾经回滚的bug
需求留意的是,当履行完最终一步记载日志『rollback finished』,其实回滚还没实在完毕。此刻节点会进入RECOVERING状况,minvalid调集中还记载了一个时刻戳区间。即节点在回滚过程中记载了需求同步到哪个OpTime,后续等同步线程追上这个时刻点后才干变成SECONDARY状况。假如在这时分,产生了同步源切换,比方切换到别的一个相同需求回滚的节点,而且又将刚刚已铲除去的commonPoint之后的oplog给同步回来,那么就或许触发第二次回滚触发assert退出。关于这个bug,MongoDB官方已在3.2.11版别中修正SERVER-25145,修正办法是在挑选同步源的时分添加是否包括minvalid中OpTime的判别。
转载请注明: 文章转载自:BETWAY官网网 https://www.nucmc.com/show-72-915-1.html