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

MongoDB技术分析(7)- 副本集选举机制

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

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


上次介绍了MongoDB复制集的总体架构,今天来介绍一下复制集的选举机制。




Raft的选举机制



作为分布式数据库,MongoDB的复制集协议来源于分布式一致性协议Raft,在分析MongoDB复制集之前,我们先简单看一下Raft的选举机制

Raft协议中包括三种角色:

  • 领导人(Leader):向其他节点发送心跳,负责处理客户端请求,并同步数据到其他节点。若收到比自己任期更新的心跳,降级为追随者。

  • 候选人(Candidate):给自己投票发起选举,获得大多数投票后成为领导人,收到领导人心跳转换为追随者。

  • 追随者(Follower):响应来自候选人和领导人的请求,如果在选举超时时间内没有收到领导人心跳,转换为候选人。



Raft算法将时间划分成任意不同长度的任期(term)。任期用连续数字表示,每一个任期从一次选举(election)开始。


一个或多个候选人试图成为领导人,赢得选举的节点在该任期内担任领导人,候选人需要获得大多数选票才能当选,所以会出现选票被瓜分,没有选出领导人的情况,这时会开始新一个任期,并马上开始新的选举。Raft算法保证在一个任期内至少要有一个领导人。



MongoDB选举机制


简单分析了Raft选举机制后,我们来看看源于Raft的MongoDB复制集成员状态机:


MongoDB复制集将其成员状态映射到不同的Raft角色上:

  • Startup2,Rollback,Recovering,Secondary对应Follower角色,可以投票们可以成为候选人;

  • Secondary同是也是候选人,可以发起选举;

  • Primary为领导人。

我们先来看一个常规的复制集启动流程: 

  • 节点初始化为Startup状态,加载了复制集配置后启动心跳,状态切换为Startup2,成为Follower


  • 节点开始初始化数据同步,状态切换为Recovering,当数据同步到集群的最小一致性时间戳(minValid)后,切换到Secondary


  • Secondary/Follower的心跳线程发现在一定时间后(选举超时时间),当前复制集视图中还没有primary/Leader时,就会切换为Secondary/Candidate发起选举。


  • 选举分为两个阶段:预选举和正式选举

  • 预选举(dry-run election):Candidate构造replSetVoteRequest命令发送到其他节点,试探自己能否赢得选举,这个过程不增加任期,如果有primary收到replSetVoteRequest发现任期比自身的新,就会开始stepdown。

  • 正式选举(real election):Candidate赢得dry-run election后,就会发起正式选举,首先增加任期并给自己投票,然后发起replSetVoteRequest命令发送到其他节点,获得大多数投票后成为Leader。


  • 作为Follower节点在收到replSetVoteRequest后,会刷新自己的任期,然后判断是否给候选人投票,投票时会判断:

  • 任期是否新

  • 协议版本是否匹配

  • 复制集名称是否匹配

  • 本节点最近提交的optime是否旧于候选人的optime

  • 在该任期内是否已经投过票


可以看出在选举过程中,有两类重要的消息交互请求:心跳消息、投票消息,我们来分析一下MongoDB对这两个请求的实现:


心跳请求

参数描述
term 任期  
setName复制集名称
heartbeatVersion心跳协议版本  
senderHost发送者ip端口 
......


心跳响应

参数描述
term 对端任期
setName对端复制集名称
state对端复制集成员状态
primaryIdprimaryId    
appliedOpTime 对端最后提交的oplog时间戳
...
...


投票请求

参数描述
term 任期  
setName复制集名称
candidateIndex 发起投票的节点在复制集视图中的id
configversion 复制集协议版本
lastDurableOpTime 最后提交并持久化的oplog的时间戳
dryRun是否为预选举


投票响应

参数描述
term term 
setName复制集名称
candidateIndex 发起投票的节点在复制集视图中的id 
staleTerm 投票人是否有更新的任期,候选人的任期过期    
votes 投票结果
primaryVote当前复制集中primary的投票结果,只在预选举(dryRun)有意义     
lastDurableOpTime 最后提交并持久化的oplog的时间戳


总体来说MongoDB复制集就是一个Raft一致性协议的具体实现,其选举在Raft基础上加入了优先级概念,让主从选举更灵活。

未完,待续。。。



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


长按二维码关注


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

评论