美文网首页
【mongoDB】mongoDB 数据同步和自动故障转移原理

【mongoDB】mongoDB 数据同步和自动故障转移原理

作者: Bogon | 来源:发表于2022-09-11 14:54 被阅读0次

    一、数据同步的原理

    当Primary节点完成数据操作后,Secondary会做出一系列的动作保证数据的同步:
    1、检查自己local库的oplog.rs集合找出最近的时间戳
    2、检查Primary节点local库oplog.rs集合,找出大于此时间戳的记录
    3、将找到的记录插入到自己的oplog.rs集合中,并执行这些操作

    PRIMARY> rs.status()
    
    {
        "set" : "test",
        "date" : ISODate("2015-07-02T02:38:15Z"),
        "myState" : 1,
        "members" : [
            {
                "_id" : 2,
                "name" : "192.168.91.144:27017",
                "health" : 1,
                "state" : 7,
                "stateStr" : "ARBITER",
                "uptime" : 1678,
                "lastHeartbeat" : ISODate("2015-07-02T02:38:14Z"),
                "lastHeartbeatRecv" : ISODate("2015-07-02T02:38:14Z"),
                "pingMs" : 1
            },
            {
                "_id" : 1,
                "name" : "192.168.91.135:27017",
                "health" : 1,
                "state" : 2,
                "stateStr" : "SECONDARY",
                "uptime" : 1678,
                "optime" : Timestamp(1435803750, 1),
                "optimeDate" : ISODate("2015-07-02T02:22:30Z"),
                "lastHeartbeat" : ISODate("2015-07-02T02:38:14Z"),
                "lastHeartbeatRecv" : ISODate("2015-07-02T02:38:13Z"),
                "pingMs" : 1,
                "syncingTo" : "192.168.91.148:27017"
            },
            {
                "_id" : 0,
                "name" : "192.168.91.148:27017",
                "health" : 1,
                "state" : 1,
                "stateStr" : "PRIMARY",
                "uptime" : 1698,
                "optime" : Timestamp(1435803750, 1),
                "optimeDate" : ISODate("2015-07-02T02:22:30Z"),
                "electionTime" : Timestamp(1435803023, 1),
                "electionDate" : ISODate("2015-07-02T02:10:23Z"),
                "self" : true
            }
        ],
        "ok" : 1
    }
    
    myState:1表示primary
    state:1表示primary;7表示arbiter
    uptime:成员的在线时间
    lastHeartbeat:当前实例到远端最近一次成功接收到心跳包的时间
    pingMs:本实例到远端路由包的来回时间
    optime:读取oplog.rs集合中本实例最近一次的更改时间
    
    

    二、mongoDB数据同步的过程:

    1:拉取同步节点的oplog。例如:Secondary节点拉去Primary节点的oplog。

    2:将拉取的oplog写入到自己的oplog中。例如:Secondary节点从Primary拉去的oplog写入到自己的oplog。

    3:请求下一个oplog同步到哪里。例如:Secondary会请求Primary节点同步到哪里了

    Secondary节点同步到哪了?

    1:Primary节点插入一条数据,同时会把该数据写入到Primary的oplog中,并且记录一个时间戳
    
    2:db.runCommand({getlasterror:1,w:2}) 在Primary节点被调用时,Primary就完成了写入操作,等待其他非仲裁节点来同步数据
    
    3:Secondary节点查询Primary的oplog并且拉取oplog
    
    4:Secondary根据时间戳应用oplog
    
    5:Secondary请求大于本身oplog时间戳的oplog
    
    6:Primary更新时间戳
    
    

    初始化同步:

    1:新增加的节点或者oplog同步时候被覆写的时候都会进行初始化同步
    
    2:从源节点取最新的oplog time,标记为start
    
    3:从源节点克隆所有的数据到目标节点
    
    4:在目标节点建立索引
    
    5:取目标节点最新的oplog time,标记为minValid
    
    6:在目标节点执行start到minValid的oplog(应该是复制过来还没有执行的oplog,没有完成最终一致性的那部分,就是一个oplog replay的过程)
    
    7:成为正常成员
    
    
    Initial Sync
     
    Initial sync copies all the data from one member of the replica set to another member. A member uses initial sync when the member has no data, such as when the member is new, or when the member has data but is missing a history of the set’s replication.
     
    When you perform an initial sync, MongoDB:
     
    1:Clones all databases. To clone, the mongod queries every collection in each source database and inserts all data into its own copies of these collections. At this time, _id indexes are also built. The clone process only copies valid data, omitting invalid documents.
    
    2:Applies all changes to the data set. Using the oplog from the source, the mongod updates its data set to reflect the current state of the replica set.
    
    3:Builds all indexes on all collections (except _id indexes, which were already completed).
    When the mongod finishes building all index builds, the member can transition to a normal state, i.e. secondary.
    
    
    

    从哪个成员来同步数据(Who to sync from)?

    MongoDB初始化同步数据的时候,可能从主节点同步,也可能是从从节点同步,根据最近的原则,选择最邻近节点去同步数据。(基于ping值)

    同时也可以用任选以下一种方式指定从哪个节点来同步数据:

    db.adminCommand( { replSetSyncFrom: "[hostname]:[port]" } )
    
    rs.syncFrom("[hostname]:[port]")
    

    新同步过来的数据并不能查看,Secondary默认不可读不可写。
    如果需要查看要执行rs.slaveOk(),则当前shell连接上可以查看,后续的其他连接还是不可读不可写。

    Primary写处理

    master负责接收写请求,具体的流程为:
    
    如果开启journal功能,则先将写请求记录到journal中,然后批量执行,同时将操作记录到oplog中
    
    如果未开启journal功能,则对每个写请求进行单独操作,然后写入oplog
    
    注:oplog是幂等的,当有累加操作inc时,会记录成set操作,从而无论重复执行多少次操作获得的结果都是一样的
    
    

    从节点同步

    如果是一个新的从节点,首先先从master的数据库文件进行复制,同时记录起始时间;当从节点从master的复制完成后,会根据复制的起始时间开始追oplog,进而与master进行同步。
    
    初始化同步完成后的Secondaty定期从Primary的oplog中获取最新的操作,然后对自己的数据副本执行这些操作,从而保证Secondaty的数据与Primary最终一致性。
    
    注意:当slave同步的速度赶不上master更新的速度时,oplog会因为追加了过多的操作而发生将旧记录覆盖掉,这样slave可能无法保证同步所有的数据,这时,slave会开始从头重新同步。
    
    

    三、 mongoDB故障自动转移

    image.png image.png image.png

    mongoDB通过lastHeartbeat来实现自动转移。

    mongod实例每隔2s就会向其他成员发送一个心跳包,并且通过rs.status()中返回的成员的health来判断成员的状态。

    当主节点与集合中的其他成员的通信electionTimeoutMillis时间超过配置的时间段(默认为10秒)时,合格的secondary节点将要求选举,以提名自己为新的主节点。

    如果primary节点不可用了,那么复制集中的所有secondary节点都会触发一次选举操作,选出新的primary节点。

    群集尝试完成新主数据库的选择并恢复正常操作。

    如果secondary节点有多个,则会选举拥有最新oplog时间戳记录的或者有较高权限的节点成为primary。

    注意:如果secondary停止时间过长,导致primary节点的oplog内容被循环写覆盖掉了,则需要手动同步secondary节点。

    节点类型

    
    
    任何时间,集群中只有一个活跃节点,其他的都是备份节点。
    有几种不同类型的节点可以存在与副本集中:
    
    standard 标准节点
    这是常规节点,它存储一份完整的数据副本,参与选举投票有可能成为活跃节点。
    
    passive 被动结点
    存储了完整的数据副本,参与投票,不能成为活跃节点,如延时节点。
    
    arbiter 仲裁者
    仲裁者只能参与投票,不接收复制的数据,也不能成为活跃节点。 
    

    节点优先级

    每个参与节点(非仲裁)有优先权,优先权按照优先值从大到小,默认优先级为1,可以是0-1000(含)。

    在节点配置中修改priority键,来配置标准节点或者被动节点:

    > members.push({"_id":3,"host":"xx.xx.xx.xx:17017","priority":40})
    

    "arbiterOnly"键可以指定仲裁节点:

    members.push({"_id":4,"host":"xx.xx.xx.xx:27017","arbiterOnly":true})
    

    备份节点会从活跃节点抽取oplog,并执行操作,就像活跃备份系统中的备份服务器一样。
    活跃节点也会写操作到自己的本地oplog,oplog中的操作包含严格递增的序号,这个序号来判定数据的时效性,所以节点之家的时间同步非常重要!

    选举策略

    如果活跃节点出现故障,其余节点会选一个新的活跃节点。
    选举过程可以由任何非活跃节点发起,新的活跃节点由副本集中的大多数选举产生。
    其中仲裁节点也参与选举,避免出现僵局。
    新的活跃节点将是优先级最高的节点,优先级相同则数据较新的节点获胜。

    不论活跃节点何时变化,新的活跃节点的数据就被假定为系统的最新数据,对其他节点(原活跃节点)的操作都会回滚,即便是之前的活跃节点已经恢复工作了。
    为了完成回滚,所有节点连接新的活跃节点后重新同步。这些节点会查看自己的oplog,找出活跃节点没有的操作,然后向活跃节点请求这些操作影响的文档最新副本。
    正在执行重新同步的节点被视为恢复中,在完成这个过程之前不能成为活跃节点的候选者。

    四、参考

    mongoDB中文手册/复写
    https://mongodb.net.cn/manual/replication/#replication-flow-control

    数据库命令 > 复制命令 > replSetSyncFrom
    https://mongodb.net.cn/manual/reference/command/replSetSyncFrom

    Replica Set Data Synchronization
    https://www.mongodb.com/docs/manual/core/replica-set-sync/#replica-set-initial-sync-source-selection

    mongoDB 副本集添加新的节点
    https://blog.csdn.net/csdnhsh/article/details/116333686

    相关文章

      网友评论

          本文标题:【mongoDB】mongoDB 数据同步和自动故障转移原理

          本文链接:https://www.haomeiwen.com/subject/pooxortx.html