本文来说下关于Raft协议有关的几个问题
概述
与Paxos不同Raft强调的是易懂(Understandability),Raft和Paxos一样只要保证n/2+1节点正常就能够提供服务;raft 把算法流程分为三个子问题:选举(Leader election)、日志复制(Log replication)、安全性(Safety)三个子问题。
概念小贴士
角色
Raft 把集群中的节点分为三种状态:Leader、Follower、Candidate,理所当然每种状态负责的任务也是不一样的,Raft运行时提供服务的时候只存在Leader与Follower两种状态;
Leader(领导者-日志管理)
负责日志的同步管理,处理来自客户端的请求,与Follower 保持这 heartBeat 的联系;
Follower (追随者-日志同步)
刚启动时所有节点为Follower状态,响应Leader的日志同步请求,响应Candidate的请求,把请求到Follower 的事务转发给Leader;
Candidate(候选者-负责选票)
负责选举投票,Raft 刚启动时由一个节点从Follower 转为Candidate 发起选举,选举出Leader 后从Candidate 转为 Leader 状态;
Term(任期)
在Raft中使用了一个可以理解为周期(第几届、任期)的概念,用Term作为一个周期,每个Term都是一个连续递增的编号,每一轮选举都是一个Term周期,在一个Term中只能产生一个Leader;当某节点收到的请求中Term 比当前Term小时则拒绝该请求。
选举(Election)
Raft的选举由定时器来触发,每个节点的选举定时器时间都是不一样的,开始时状态都为Follower 某个节点定时器触发选举后Term 递增,状态由Follower转为Candidate,向其他节点发起 RequestVote RPC请求,这时候有三种可能的情况发生:
- 该RequestVote 请求接收到n/2+1(过半数)个节点的投票,从Candidate转为Leader,
向其他节点发送heartBeat 以保持Leader 的正常运转。 - 在此期间如果收到其他节点发送过来的 AppendEntries RPC请求,如该节点的 Term大则当前节点转为Follower,否则保持Candidate 拒绝该请求。
- Election timeout 发生则 Term 递增,重新发起选举
在一个 Term 期间每个节点只能投票一次,所以当有多个Candidate 存在时就会出现每个Candidate 发起的选举都存在接收到的投票数都不过半的问题,这时每个Candidate 都将Term递增、重启定时器并重新发起选举,由于每个节点中定时器的时间都是随机的,所以就不会多次存在有多个Candidate 同时发起投票的问题。
在Raft中当接收到客户端的日志(事务请求)后先把该日志追加到本地的Log中,然后通过heartbeat 把该Entry 同步给其他 Follower,Follower 接收到日志后记录日志然后向Leader 发送ACK,当Leader 收到大多数(n/2+1)Follower 的 ACK信息后将该日志设置为已提交并追加到本地磁盘中,通知客户端并在下个 heartbeat 中Leader 将通知所有的 Follower 将该日志存储在自己的本地磁盘中。
安全性(Safety)
安全性是用于保证每个节点都执行相同序列的安全机制如当某个 Follower 在当前Leader commit Log 时变得不可用了,稍后可能该Follower 又会倍选举为Leader,这时新Leader 可能会用新的Log覆盖先前已committed的Log,这就是导致节点执行不同序列;Safety就是用于保证选举出来的Leader一定包含先前 commited Log的机制;
选举安全性(Election Safety):每个 Term 只能选举出一个Leader。
Leader 完整性(Leader Completeness):这里所说的完整性是指Leader 日志的完整性,Raft在选举阶段就使用Term的判断用于保证完整性:当请求投票的该Candidate 的Term较大或 Term 相同Index 更大则投票,该节点将容易变成 leader。
raft协议和zab协议区别
相同点
- 采用quorum来确定整个系统的一致性,这个quorum一般实现是集群中半数以上的服务器,
- zookeeper 里还提供了带权重的 quorum 实现.
- 都由 leader 来发起写操作.
- 都采用心跳检测存活性
- leader election 都采用先到先得的投票方式
不同点
- zab用的是epoch和count的组合来唯一表示一个值,而raft用的是term和index
- zab的follower在投票给一个leader之前必须和leader的日志达成一致,而raft的follower则简单地说是谁的 term高就投票给谁
- raft 协议的心跳是从leader到follower,而 zab 协议则相反
- raft 协议数据只有单向地从leader到follower(成为leader的条件之一就是拥有最新的log)
而zab协议在 discovery 阶段,一个 prospective leader 需要将自己的log更新为 quorum 里面最新的log,然后才好在synchronization 阶段将quorum 里的其他机器的log都同步到一致。
本文小结
本文详细介绍了Raft协议相关的内容。