开发者学堂课程【MongoDB 快速入门:复制集使用及原理介绍】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/49/detail/1002
复制集使用及原理介绍(二)
三、MongoDB 副本集原理介绍
1、什么是 MongoDB Oplog
接下来进行MongoDB副本集原理介绍,首先前面多次提到MongoDB的oplog,oplog在MongoDB里面也有非常重要的地位,MongoDB Oplog是local库下的集合,也就是它是一个表,不是一个专门的所谓的binlog日志,是用来专门保存写操作所产生的增量日志的,类似于MySQL中的Binlog,它在 MongoDB下机制是不一样的。它是一个Capped Collection,即超出配置的最大值后,会自动删除最老的历史数据,MongoDB针对Oplog的删除有特殊优化,以提升删除效率。当oplog用满之后,每一次新的写操作都会产生新的oplog都会导致oplog去触发删除的情况,这个优化是非常有必要的。当主节点产生新的Oplog Entry,被节点通过fed命令加上get more把oplog拉过来应用在自己的节点之上,然后保持着和主节点状态一致。Oplog目前包含的参数:像o是插入或更新的内容,op是操作类型,ns是操作执行的DB和集合,ts是操作发生的时间等。这个其实官网都有,可以查看官网的文档。
2、oplog 保留策略——根据大小及根据时间范围
简单介绍oplog的保留策略根据大小和时间范围。在4.4之前:根据replication.oplogSizeMB的配置决定Oplog集合的大小上限,默认为磁盘空间的5%,这里需要注意当一个单击多实例的部署形态可能需要调整值,比如一个机器上布了10个可能就要占用50%的磁盘空间,这显然是不能接受的,当Oplog集合大小超过上限时,MongoDB会触发自动删除最老的Oplog Entry。在4.4阿里云刚刚上线的版本也是有增强的,MongoDB提供了按时间段来保留Oplog,由参数storage.oplogMinRetentionHours控制,这个主要是方便更好的做一些定期的维护的操作。删除时,即使Oplog集合大小超过了配置的最大值,比如配置了20G,如果超过了20G,但是老的oplog仍然在storage.oplogMinRetentionHours范围内,那么Oplog不会删除。需要注意的是MongoDB官方目前提供了在线修改oplogMinRetentionHours的配置值的方式,不需要去重启实例。
3、MongoDB 副本集同步原理——全量同步
下面进行MongoDB副本集同步原理进行介绍,同步包括两部分一个是全量同步一个是增量同步。
先来看全量同步,全量同步发生的时机就是新节点刚加入副本集的时候,这时它是空的状态,需要去把当前的全量数据复制过来,第二个就是因为老的同步滞后,滞后太久oplog已经被删除只能进入recovering状态,这时也需要去做全量同步。全量同步包含两个阶段,一个是数据克隆阶段:记录开始时间T1,从源端拉取所有的集合数据,不保证数据和源的一致性,记录结束时间T2,接着是增量应用阶段:应用从T1-T2期间的Oplog,达到一致性状态,全量同步结束。可以看全量同步之间的流程图。
首先是初始化副本集的配置,副本集会进入STARTUP2的状态,选择同步源,这一步如果失败的话1秒后重新选择同步源,接着是清理当前的数据,删除除local库以外的所有DB,从同步源获取being Fetching Timestamp/beingApplyingTimestamp,然后会去初始化后台的限制,后台的限制会初始化OplogFetcher,从being FetchingTimestamo持续拉取oplog到临时集合,这是后台所做的事情,全量同步还会获取所有DB列表,初始化DatabaseCloner获取所有集合列表,再去初始化CollectionCloner,克隆集合和索引,这是一个不断循环的过程,直到将DB下所有的集合完成克隆,最后将DB完成克隆,完成DB克隆之后克隆阶段就结束了,会从同步源获取stopTimestamp,克隆时间结束的一个点就会从oplog临时集合读取oplog,从beginApplyingTimestamp开始批量开发应用oplog,到stopTimestamp为止,最后检查同步源是否发生了回滚。因为如果发生了回滚,则说明oplog数据不是处于一致性的状态,需要重新去做全量同步,最后当检查通过会进入secondary达到一致性状态,这样就结束了。
4、4.4增强——全量同步断点续传
4.4之前:全量同步期间,如果发生网络异常,导致同步终端,需要重头开始。网络环境比较差时,大数据量很难完成全量同步,可用节点数变少,实例可用性存在隐患。4.4:基于resume token机制,记录全量拉取的位点,网络异常导致同步中断后,重连时带上resume token,resume token本质上是之前拉取的集合中的一个reackid的概念,会从breaker继续拉取增量来保证断点续存,当全量同步因为网络中断,而不断的去重试,重试是有超时时间的,是由replication.initialSyncTransientErrorRetryOeriodSecond参数来决定的,默认时间为24h。
5、MongoDB 副本集同步原理——增量同步
对增量同步进行简要的介绍,首先增量同步发生的时机是比较简单的:全量同步结束后,从节点为了保证和主节点数据的一致,会持续的去做同步,官方也将他称为stand replication,来保持和主节点数据的一致。这里从不同的工作线程分析具体的流程:首先会有oplogFetcher线程负责拉取oplog:find命令创建tailable cursor,getMore命令批量从同步源拉取oplog,单个batch最大16MB。拉取的oplog batch放到内存的blocking queue中,queue也是有限制的,512兆的限制。replBatcher线程负责从blockingqueue中取出batch生成新的可apply的batch,放到deque中,这里主要是因为需要控制并发,比如说一些ddl操作和一些写操作不能去并发的apply,需要将ddl放到一个单独的batch。最后oplogApplier线程负责从deque中取出batch,写oplog,然后把batch拆分,分发到worker线程进行并发apply。为了保持一致性,中间需要保存多个不同的oplog应用位点信息,比如说oplogafter、oplogthrough等等这样的信息,这里其实上有比较详细的信息可参考,可以通过链接去看更详细的过程。
6、MongoDB 副本集高可用原理
高可用也就是主备切换的时机一个是说主节点本身不可用,另外一个是新增的节点,比如说是更高的priority需要去抢占主节点的角色。另外就是主动运维,比如rs.stepDown或者是rs.recondfig。MongoDB基于Raft协议实现了自己的高可用机制,副本集之间保持心跳,默认两秒一次。如果超出electionTimeoutMillis,默认10秒没有探测到主节点,secondary节点会发起选举,发起前检查自身条件:priority是否大于0,有没有资格成为组,当前的状态是否够新,比如和其他的节点相比,同步是否滞后太久。在真正的选举前,会先进行一轮空投(dry-run),避免当前primary无意义的降级(stepDown),因为primary如果收到了其他节点的选举的请求return更高的话,实际上是会降级的。Dry-run成功后,会增加自身的term,发起真正的选举,如果收到多数派的选票,那么选举成功,把新的拓扑信息通过心跳广播到整个副本集。以上就是这次课程的主要内容。
四、复制集使用及原理介绍课程总结
副本集是可用性,扩展性、维护性的有效保证,在中等业务规模清况下,生产环境建议优先选择部署该形态。在较大业务规模下,使用shine形态。不管哪种形态都不建议使用standnoot的模式。第二副本集使用务必使用高可用连接串的方式,避免业务访问单点。默认情况下的read/write Concern可以满足绝大部分业务需求,从刚才的介绍可以看到 read concern初始化还是比较复杂的,大部分情况下保持默认值就是可以的。特殊情况需要在一致性和性能之间做出取舍,配置read和concern的值。第三Oplog是MongoDB的重要基础设施,除了用于同步 (全量+增量),还可用于构建数据生态( changeStream),即MongoDB提供的changeStream功能。第四MongoDB以Raft协议为指导实现了自己的高可用机制,大部分情况下,主节点故障, 15秒内可选出新主,所以要对MongoDB高可用有足够的信心。