MongoDB原理:复制集状态同步机制

MongoDB复制集(3.0版本)之间通过心跳信息来同步成员的状态信息,每个节点会周期性的向复制集内其它的成员发送心跳信息来获取状态,如rs.status()看到的复制集状态信息。

一次心跳请求分3个阶段 (主动发起心跳请求的节点称为源,接受到心跳请求的成为目标)

  1. 源向目标发送心跳请求
  2. 目标处理心跳请求,并向源发送应答
  3. 源接受到心跳应答,更新目标节点状态

接下来将介绍这3个阶段里的主要状态同步逻辑

阶段1

默认配置下,复制集的节点每隔2s会向其他成员发送一次心跳请求,即发送replSetHeartbeat命令请求,心跳请求的内容类似如下(通过mongosniff抓包获取),主要包含replSetName、发送心跳的节点地址、复制集版本等。

command: replSetHeartbeat database: admin metadata: { $replData: 1 } commandArgs: { replSetHeartbeat: "mongo-9552", pv: 1, v: 22, from: "10.101.72.137:9552", fromId: 3, checkEmpty: false }

阶段2

复制集成员收到心跳请求后,就开始处理请求,并将处理的结果回复给请求的节点。

  • 如果自身不是复制集模式、或复制集名称不匹配,则返回错误应答
  • 如果源节点的复制集配置(rs.conf()的内容)版本比自己低,则将自身的配置加入到心跳应答消息里
  • 将节点自身的oplog及其他状态信息等加入到心跳应答消息
  • 如果自身是未初始化状态,则立即向源节点发送心跳请求,以更新复制集配置
        commandReply: { ok: 1.0, time: 1460705698, electionTime: new Date(6273289095791771649), e: true, rs: true, state: 1, v: 22, hbmsg: "", set: "mongo-9552", opTime: new Date(6272251740930703361) } metadata: { $replData: { term: -1, lastOpCommitted: { ts: Timestamp 1460372410000|1, t: -1 }, lastOpVisible: { ts: Timestamp 0|0, t: -1 }, configVersion: 22, primaryIndex: 2, syncSourceIndex: -1 } }
    

阶段3

阶段3是最主要的处理部分,节点收到心跳应答后,会根据应答消息来更新对端节点的状态,并根据最终的状态确定是否需要进行重新选举。

  • 收到心跳应答时,如果是错误应答(心跳消息超时未应答相当于收到了错误应答),则

    • 如果当前重试次数 <= kMaxHeartbeatRetries(默认为2),并且上一次发送心跳在kDefaultHeartbeatTimeoutPeriod(默认为10)时间内,则立即发送下一次心跳
    • 当失败次数超过kMaxHeartbeatRetries,或者上一次心跳时间到现在超过kDefaultHeartbeatTimeoutPeriod,则认为节点down
  • 如果对端的复制集版本比自己高,则更新自己的配置并持久化到local数据库中
  • 根据应答消息更新对端的状态信息
  • 如果自身是主节点,当发现有优先级更高的节点可被选为主,则主动降级
  • 如果其他是主节点,但自身有更高的优先级并可被选为主,则会主动要求主节点降级(目前这个逻辑实现有bug,主要靠主节点主动降级来保证优先级最高的节点最终会变成主, https://jira.mongodb.org/browse/SERVER-23630
  • 如果当前没有主节点,则主动发起新的选举,当得到大多数节点同意后,即可选出新的主节点

总的来说,MongoDB通过心跳来同步节点间信息并触发选举,最终将复制集达到统一的状态,但过程的正确性没有理论依据,MongoDB-3.2版本里,使用了新版本的复制集通信协议,改用raft来选举,能进一步降低故障发现恢复时间,目前还在学习中。

时间: 2024-10-29 12:38:47

MongoDB原理:复制集状态同步机制的相关文章

mongodb数据库复制集随机同步数据

记一次MongoDB主从切换,重新同步数据. PRIMARY> rs.conf() { "_id" : "poptask", "version" : 4, "members" : [ { "_id" : 0, "host" : "10.0.0.105:20011" }, { "_id" : 1, "host" : &quo

MongoDB基于复制集创建索引

MongoDB在启用复制集(Replica Set)功能后,原先一个简单的索引添加,在之上会变得相对复杂,尤其是在数据量巨大的时候,需要考虑尽可能将性能影响降低到最小.基于此我们需要采取逐个节点创建索引的方式来达成.如下本文描述. 一.复制集索引创建的过程 MongoDB从节点上复制集上索引的创建,通常是在主节点索引创建完成之后. 在分片集群环境中,mongos将发送createindex()命令到每一个shard的主成员节点, 当主副本成员完成索引创建后,辅助副本开始创建索引. 二.如何最小化

通信 tcp wifi-多节点状态同步机制设计

问题描述 多节点状态同步机制设计 一个例子 A通过wifi 控制B B通过串口控制单片机C C的每个io控制一个灯 一共20个灯 应用 ABC 上面都有指示的东西 表示哪个灯亮了 问题1:比如A要控制最终的某个灯 怎么能保证 A B C 上的 指示是同步的不会错? 问题2:A,B,C都有自己的数据库 比如A想改C的某些配置 怎么能保证长时间使用过程中数据库不出错 他们几个的数据库版本是一致的 如果整条链路间做应答机制应该怎么做 问题3:概念问题 怎么确认通信是成功的 A发给 B B回复收到 A回

MongoDB数据库复制集同步原理与例子

同步过程 选取从哪个节点同步后,拉取oplog 1.Applies the op执行这个op日志 2.Writes the op to its own oplog (also local.oplog.rs)将这个op日志写入到自己的oplog中 3.Requests the next op请求下一个op日志secondary节点同步到哪了 secondary节点同步到哪了 主节点根据从节点获取oplog的时间戳可以判断数据同步到哪了 How does primary know where sec

MongoDB 3.4 复制集全量同步改进

3.2版本复制集同步的过程参考MongoDB 复制集同步原理解析 在 3.4 版本里 MongoDB 对复制集同步的全量同步阶段做了2个改进 在拷贝数据的时候同时建立所有的索引,在之前的版本里,拷贝数据时会先建立_id索引,其余的索引在数据拷贝完之后集中建立 在拷贝数据的同时,会把同步源上新产生的oplog拉取到本地local数据库的临时集合存储着,等数据全量拷贝完,直接读取本地临时集合的oplog来应用,提升了追增量的效率,同时也避免了同步源上oplog不足导致无法同步的问题. 上图描述了这2

MongoDB复制集同步原理解析

MongoDB副本集数据同步](https://docs.mongodb.com/manual/core/replica-set-sync/)主要包含2个步骤 intial sync,可以理解为全量同步 replication,追同步源的oplog,可以理解为增量同步 本文是对MongoDB高可用复制集原理的补充,会详细介绍MongoDB数据同步的实现原理. initial sync Secondary节点当出现如下状况时,需要先进行全量同步 oplog为空 local.replset.minv

MongoDB复制集原理

复制集简介 Mongodb复制集由一组Mongod实例(进程)组成,包含一个Primary节点和多个Secondary节点,Mongodb Driver(客户端)的所有数据都写入Primary,Secondary从Primary同步写入的数据,以保持复制集内所有成员存储相同的数据集,提供数据的高可用. 下图(图片源于Mongodb官方文档)是一个典型的Mongdb复制集,包含一个Primary节点和2个Secondary节点. Primary选举 复制集通过replSetInitiate命令(或

MongoDB 复制集(Replica Set)

复制集(replica Set)或者副本集是MongoDB的核心高可用特性之一,它基于主节点的oplog日志持续传送到辅助节点,并重放得以实现主从节点一致.再结合心跳机制,当感知到主节点不可访问或宕机的情形下,辅助节点通过选举机制来从剩余的辅助节点中推选一个新的主节点从而实现自动切换.这个特性与MySQL MHA实现原理一样.本文主要描述MongoDB复制集并给出创建复制集示例以及完成自动切换. 一.复制集相关概念 复制集 复制是在多台服务器之间同步数据的过程,由一组Mongod实例(进程)组成

MongoDB管理:如何优雅的重启复制集?

啊!你还不了解MongoDB复制集?先看这里科普一下 复制集的成员启动后,会选举出一个Primary,Primary需要得到大多数成员的投票.所有的写入操作都必须向Primary发起,通过oplog将写操作同步到Secondary. 在复制集运行的过程中,难免会遇到需要重启节点的场景,比如复制集版本升级.节点维护等,在重启节点的过程中,建议不要直接shutdown Primary,这样可能导致已经写入primary但未同步到secondary的数据丢失,过程类似如下: shutdown Prim