Raft 简介

共识是分布式容错系统的基础问题,是指多个服务器对值达成一致。

raft 设计目的:

  1. 易于理解
  2. 跟 Paxos 有同等容错能力和性能

raft 服务器状态:

  1. 领导(leader):处理所有客户端请求
  2. 跟随者(follower):被动响应候选人和领导
  3. 候选人(candidate):中间状态,在选举时出现

领导选举(Leader election)

terms(任期)

  1. 所有的服务器管理着当前任期:
    • 任期单调递增
    • 作为逻辑时钟管理
    • 无论服务器在何时进行通信,任期会进行交换
  2. 任期交换规则:
    • 当 A 的任期大于 B 的任期时,B 更新任期为 A 的
    • 当 A 的任期大但 B 认为自己才是领导时,B 回归跟随者状态
    • 当 A 的任期大但收到来自 B 的请求时,A 拒绝 B 的请求,B 更新任期后再发出请求

跟随者状态

  1. 所有服务器都是从跟随者状态开始
  2. 所有服务器都有本地的计时器
  3. 只要在计时内能收到来自领导或候选人的消息(心跳消息),就一直保持跟随者状态
  4. 当计时内未收到心跳消息,则认为系统没有存活的(viable)领导,开始选举流程,自提名(nominate)为候选人

如何解决多个跟随者自提名为候选人的问题?各个服务器使用随机的计时超时

候选人状态

  1. 跟随者进入后续人状态过程:增加当前任期,并设置状态为候选人
  2. 给自己投一票,然后再发送投票请求到其他服务器
  3. 其他服务器收到投票请求后,会增加任期,然后投票
  4. 候选人计票,当得到大多数选票后,转为领导状态,并发送心跳消息;若落选,退出到跟随者状态。

日志复制(Log replication)

日志:

  1. 每个节点都维护着一份操作日志(action log)
  2. 日志中的每一条目(entry)包括:操作和任期(action and term),任期表示节点接收到操作的时间。

复制过程:

  1. 当客户端请求进入领导节点时(rd<-Ready),领导节点先追加条目到自身的日志中(storage append rd.Entrieds)
  2. 接下来,领导节点告知其他节点追加条目,并等待确认追加( transport send rd.Messages)
  3. 正如选举过程,复制过程也是遵循少数服从多数的原则,当收到大多数节点的确认时,领导会提交条目(commit entry),然后更新状态机,再回复成功消息给客户端和其他节点。(applyConfChange & advance)

如果跟随者失败了,领导会不断尝试去追加,一旦跟随者复活,条目会被最终提交。

如果领导失败了,那么条目将不会被提交,进入下个任期选举,并产生新的条目。

etcd-raft

go.etcd.io/etcd/raft/v3

etcd/raft 中的心跳和选举周期都是通过逻辑时钟控制的,一般设置心跳周期为1 个逻辑时钟,选举周期为 10 个逻辑时钟。接入 etcd/raft 时,需要自定义一个 Ticker,然后在 tick 之后,以心跳为例,内部会将 heartbeatElapsed 自增,然后判断是否到达设定的 Timeout,到达则恢复 heartbeatElapsed 为 0,并执行心跳操作。

参考

FSM ppt

https://raft.github.io/

https://db.cs.duke.edu/courses/compsci512/spring15/lectures/raft-guest.pptx

http://thesecretlivesofdata.com/raft/

posted @ 2022-05-05 16:07  東籬老農  阅读(84)  评论(0编辑  收藏  举报