暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MongoDB技术分析(8)- 副本集数据同步机制

数据库及存储技术 2021-04-16
2093

分布式系统最本质的功能是通过提供数据冗余存储能力,提高系统的持久度和可用性,这也是分布式NOSQL系统最复杂的一块,笔者准备从整体架构、选举、数据同步、故障处理等几个维度逐步揭示MongoDB副本集功能的原理。


上次介绍了MongoDB复本集的选举机制,今天来介绍一下复本集的数据同步机制。MongoDB复本集基于Raft一致性协议,我们先来看一下Raft的数据同步机制。




Raft数据同步机制


Raft一致性算法基于复制状态机,复制状态机是通过复制日志来实现的。每一台服务器保存着一份日志,日志中包含一系列的命令,状态机会按顺序执行这些命令。

因为每一台计算机的状态机都是确定的,所以每个状态机的状态都是相同的,执行的命令是相同的,最后的执行结果也就是一样的了。


应用于实际系统的一致性算法一般有以下特性:

  • 高可用性,只要集群中的大多数节点都能运行,可以互相通信并且可以和客户端通信,这个集群就可用。因此,一般来说,一个拥有3台节点的集群可以容忍其中1台节点的崩溃。

  • 不依赖时序保证一致性,时钟错误和极端情况下消息延迟的情况下才会引起可用性问题。

  • 通常情况下,大多数节点作出响应则认为完成,一少部分慢的机器不会影响系统的整体性能。


MongoDB复本集数据同步机制


MongoDB副本集数据同步分为两种:初始同步 和 稳定同步


初始同步(initial sync)

初始同步发生在一个节点刚加入复本集时,节点首先会在复本集中选择一个同步源,然后会重建本地的oplog,再启动一个oplogFetcher从同步源拉取oplog缓存在本地。

初始化同步的意义是让节点通过该步骤同步数据后,让副本集达到一个一致性状态,以便进入后面的稳定同步。

但是由于在同步过程中同步源可能还在接收业务,数据在不断变化,那么何时能达到所谓的一致性状态?

故MongDB将始同步定义为两个阶段:Clone和application。

  • 在clone阶段,可以理解为一个全量拷贝阶段,通过DatabaseCloner和CollectionCloner读取同步源存量数据。

  • 在application阶段,新加入节点首先向同步源查询当前最新apply的Oplog的OpTime,把这个OpTime作为之前提到的一致性点(minValid),然后开始回放oplog缓存中的操作直到这个minValid。

初始化同步完成后,节点就进入了稳定同步状态。


稳定同步(SteadyStateReplication)

在稳定同步状态,后台会启动三个线程:

  • OplogFetcher:从同步源拉取oplog缓存在本地。

  • OplogApplier:从缓存中读取Oplog在本地回放,更新lastAppliyOpTime和lastDurableTime。

  • OplogReporter:向同步源汇报本节点已经回放的oplog的lastAppliyOpTime和lastDurableTime,同步源收到汇报后会刷新Topology视图。


同步源选择

同步源选择分两个步骤:同步源候选人选择和同步源探测。

节点在选择同步源候选人的时候,首先会考虑用户的replSetSyncFrom命令,优先遵从用户指令。

然后会检测settings.chainingAllowed配置是否开启,如果没有开启,默认选择primary为同步源。否则按照:

  • 查看Topology视图中Primary的最近OpTime,如果有别的节点的最近OpTime在Primary的Optime后面,则排除这个节点作为同步源候选人。

  • 选择Ping时延最小的节点作为同步源候选人。

  • 如果没有节点符合条件,1秒后重新开始选择。


选择了候选人后,就进入同步源探测阶段,确保该同步源可以提供Oplog:

  • 检查同步源是否有oplog,没有则加入黑名单,下次不会选择其作为候选人。

  • 检查同步源最老的oplog是否新于本节点最新的oplog,如果是则加入黑名单,下次不会选择其作为候选人。

  • 如果本节点有之前提到的一致性时间点minValid,那么检查同步源是否也有,没有则加入黑名单,下次不会选择其作为候选人。


讲完数据同步的主要架构和流程,我们再来看看数据同步的载体:Oplog


Oplog结构

  • ts: 操作发生的时间

  • h: 记录的唯一ID

  • v: 版本信息

  • op: 操作的类型

  • ns: 操作针对的数据库、表

  • o2: 更新时的过滤条件

  • o: 操作针对的文档

举例如下:

    {
        "ts" : Timestamp(1466585597, 1),  
        "h" : NumberLong("-9079402863358495470"),  
        "v" : 2,  
        "op" : "u",  
        "ns" : "test.user",
        "o2" : {
            "_id" : ObjectId("576a51c7e8696f07b2b0b272")
        },
        "o" : {
            "_id" : ObjectId("576a51c7e8696f07b2b0b272"),
            "name" : "xxx"
        }
    }


oplog在回放时具备幂等性,多次回放同一条oplog不会影响数据结果,保证upsert语义。


总结

MongoDB复本集通过OpLog的同步,保证复本集的数据一致性。通过lastApplyOptime和lastDurableOptime的反馈,实现了在所有节点上的一个一致性视图,这样可以很方便为用户提供不同级别的一致性IO服务:WriteConcern/ReadConcern。


未完待续。。。



..........................  END  ..........................


长按二维码关注


文章转载自数据库及存储技术,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论