深入理解Raft算法

前言

最近在分布式系统一致性方面,Raft算法比较火啊。所以就抽时间看了下这个算法。

之前已经有Paxos算法,用于解决分布式系统最终一致性问题,而且已经有了zookeeper这个成熟的开源实现。那么这个Raft算法有啥用呢?按照Raft官网的说法,这个算法的错误容忍和性能和Paxos算法类似,但是拥有更加简单易懂的设计。

看过Paxos算法的童鞋们都知道,这货复杂地和屎一样,为了实现去中心化而考虑了各种复杂的边界条件和时序下的可靠性。而Raft算法则根据实际应用中的需要,简化了设计模型,不采用去中心化设计,而是自动选择中心阶段,并且在各种情况和时序下可以保证能够正确的选择出中心节点并保证数据的一致性。而且也正是由于能够选举出唯一的主节点(Leader)使得整个通信流程非常地简单,并且易于理解和维护。

那么它是如何做到这些的呢?

基本算法设计

Raft的基本设计可以参照官网介绍 https://raft.github.io/

官方网站上的图例可以点击节点,然后模拟节点crash或者超时或者收到请求时的通信流程。其实也是一个javascript的简单实现,有利于我们理解Raft算法的流程。

另外还有一个基本要点的流程有点像PPT的东东也能帮助我们理解 http://thesecretlivesofdata.com/raft/

当然最完整的就是这篇Paper了,《In Search of an Understandable Consensus Algorithm (Extended Version)》。大体翻译提取下这篇论文里的核心内容吧。

基本思路是每个节点分为Leader、Follower、Candidate三个状态。

  • Leader: 主节点
  • Follower: 从节点
  • Candidate: 正在竞选主节点(参选节点)

消息状态分为:

  1. Uncommit: 未提交转态(Client发到主节点,主节点还没有得到大多数从节点的提交回执)
  2. Commited: 已提交转态(从节点收到主节点的消息提交,还未收到确认报文)
  3. Applied: 已确认转态(从节点收到主节点的确认报文,或主节点已收到大多数从节点的提交回执)

所有的节点中都要记录以下信息

  • CurrentTerm: 节点的当前选举版本号(发起竞选主节点时要更新这个值),后面的Term指代消息中的选举版本号或者生产消息时的选举版本号
  • Voted For: 主节点投票给谁
  • Log: log是论文里的描述,其实也就是消息的内容,后面用消息指代这里提到的Log
  • Commit Index: 提交序号(每次收到客户端消息时要更新这个值)
  • LastApplied: 最后确认的消息序号
  • 下面是仅主节点需要记录的数据
  • NextIndex[]: 预估的每个从节点下一个的Log的序号(初始化为最后的log索引+1)
  • MatchIndex[]: 已经确认的每个从节点的下一个Log的序号(初始化为0)

RPC消息有两种:

AppendEntries RPC(心跳、消息同步RPC)

RPC请求:

RPC回复:

收方判定条件

  1. 如果请求包内Term < CurrentTerm,回复失败
  2. 如果节点内不包含Term等于PrevLogTerm但CommitIndex不等于PrevLogIndex的消息,则回复失败
  3. 如果存在消息和拿到的请求包里的冲突(CommitIndex相同但Term不同),则移除所有冲突之后的消息,并用新的消息覆盖
  4. 如果消息不在已有消息集合中,追加数据
  5. 如果LeaderCommit大于本地的CommitIndex,CommitIndex要设置成LeaderCommit和最后一条消息(Entries)的CommitIndex里的最小值

RequestVote RPC(竞选主节点RPC)

RPC请求:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值