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来选举,能进一步降低故障发现恢复时间,目前还在学习中。

作者简介

张友东,阿里巴巴技术专家,主要关注分布式存储、Nosql数据库等技术领域,先后参与TFS(淘宝分布式文件系统)AliCloudDB for Redis等项目,目前主要从事AlidCloud For MongoDB的研发工作,致力于让开发者用上最好的MongoDB云服务。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
为了部署 MongoDB 复制,您需要按照以下步骤进行操作: 1. 安装 MongoDB:首先,您需要在每个复制成员的机器上安装 MongoDB。您可以从 MongoDB 官方网站下载适合您操作系统的安装程序,并按照说明进行安装。 2. 创建数据目录:在每个复制成员的机器上,创建用于存储数据的目录。您可以使用 `mkdir` 命令创建目录,例如 `mkdir /data/db`。 3. 配置复制成员:对于每个复制成员,您需要在 MongoDB 配置文件中指定以下配置项: - `replSet`:指定复制的名称,例如 `replSet=rs0`。 - `dbpath`:指定数据目录的路径,例如 `dbpath=/data/db`。 - `port`:指定 MongoDB 实例的端口号,默认为 27017。 您可以通过编辑 MongoDB 配置文件(通常位于 `/etc/mongod.conf`)来进行这些配置。 4. 启动复制成员:在每个复制成员的机器上,使用命令行启动 MongoDB 实例。例如,使用以下命令启动一个实例:`mongod --config /etc/mongod.conf`。 5. 初始化主节点:选择一个节点作为初始主节点,并连接到该节点的 MongoDB 实例。在 MongoDB shell 中执行以下命令初始化主节点: ``` rs.initiate() ``` 6. 添加其他节点:将其他节点添加到复制中。在 MongoDB shell 中执行以下命令,将节点添加为副本成员: ``` rs.add("hostname:port") ``` 其中 `hostname:port` 是要添加的节点的主机名和端口号。 7. 验证复制状态:执行以下命令,验证复制状态: ``` rs.status() ``` 此命令将显示复制状态信息。 完成以上步骤后,您的 MongoDB 复制就部署好了。您可以添加更多的节点,并参考 MongoDB 文档以了解更多复制的配置和管理选项。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值