介绍

Raft 状态

一个 Raft 集群包含若干个服务器节点;通常是 5 个,这允许整个系统容忍 2 个节点的失效,每个节点处于以下三种状态之一:

  • follower :所有结点都以 follower 的状态开始。如果没收到leader消息则会变成 candidate状态。
  • candidate:会向其他结点“拉选票”,如果得到大部分的票则成为leader。这个过程就叫做Leader选举(Leader Election)。
  • leader:所有对系统的修改都会先经过leader。

Raft 一致性算法

Raft通过选出一个leader来简化日志副本的管理,例如,日志项(log entry)只允许从leader流向follower。

基于leader的方法,Raft算法可以分解成三个子问题:

  • Leader election (领导选举):原来的leader挂掉后,必须选出一个新的leader
  • Log replication (日志复制):leader从客户端接收日志,并复制到整个集群中
  • Safety (安全性):如果有任意的server将日志项回放到状态机中了,那么其他的server只会回放相同的日志项

Leader election (领导选举)

Raft 使用一种心跳机制来触发领导人选举。当服务器程序启动时,他们都是 follower(跟随者) 身份。如果一个跟随者在一段时间里没有接收到任何消息,也就是选举超时,然后他就会认为系统中没有可用的领导者然后开始进行选举以选出新的领导者。要开始一次选举过程,follower 会给当前term加1并且转换成candidate状态。

然后他会并行的向集群中的其他服务器节点发送请求投票的 RPCs 来给自己投票。候选人的状态维持直到发生以下任何一个条件发生的时候.

  • 他自己赢得了这次的选举

    • 如果这个节点赢得了半数以上的vote就会成为leader,每个节点会按照first-come-first-served的原则进行投票,并且一个term中只能投给一个节点, 这样就保证了一个term最多有一个节点赢得半数以上的vote
    • 当一个节点赢得选举, 他会成为leader, 并且给所有节点发送这个信息, 这样所有节点都会回退成follower。
  • 其他的服务器成为领导者,如果在等待选举期间,candidate接收到其他server要成为leader的RPC,分两种情况处理:

    • 如果leader的term大于或等于自身的term,那么改candidate 会转成follower 状态
    • 如果leader的term小于自身的term,那么会拒绝该 leader,并继续保持candidate 状态
  • 一段时间之后没有任何一个获胜的人

    • 有可能,很多follower同时变成candidate,导致没有candidate能获得大多数的选举,从而导致无法选出leader。当这个情况发生时,每个candidate会超时,然后重新发增加term,发起新一轮选举RPC。需要注意的是,如果没有特别处理,可能出导致无限地重复选主的情况。
    • Raft采用随机定时器的方法来避免上述情况,每个candidate选择一个时间间隔内的随机值,例如150-300ms,采用这种机制,一般只有一个server会进入candidate状态,然后获得大多数server的选举,最后成为主。每个candidate在收到leader的心跳信息后会重启定时器,从而避免在leader正常工作时,会发生选举的情况。

Log replication (日志复制)

当选出 leader 后,它会开始接受客户端请求,每个请求会带有一个指令,可以被回放到状态机中。leader 把指令追加成一个log entry,然后通过AppendEntries RPC并行的发送给其他的server,当该entry被多数派server复制后,leader 会把该entry回放到状态机中,然后把结果返回给客户端。

当 follower 宕机或者运行较慢时,leader 会无限地重发AppendEntries给这些follower,直到所有的follower都复制了该log entry。

Raft的log replication保证以下性质(Log Matching Property):

  • 如果两个log entry有相同的indexterm,那么它们存储相同的指令
  • 如果两个log entry在两份不同的日志中,并且有相同的indexterm,那么它们之前的log entry是完全相同的

其中特性一通过以下保证:

  • leader在一个特定的termindex下,只会创建一个log entry
  • log entry不会改变它们在日志中的位置

特性二通过以下保证:

  • AppendEntries会做log entry的一致性检查,当发送一个AppendEntriesRPC时,leader会带上需要复制的log entry前一个log entry的(index, iterm),如果follower没有发现与它一样的log entry,那么它会拒绝接受新的log entry 这样就能保证特性二得以满足。

动画演示Raft流程

http://thesecretlivesofdata.c...

go实现Raft

项目地址

https://github.com/goraft/raft

数据结构

https://blog.csdn.net/xiongwe...

goraft主要抽象了server、peer和log三个结构,分别代表服务节点、Follower节点和日志。

server

Raft作为一种多节点状态一致性维护协议,运行过程中必然涉及到多个物理节点,server就是用来抽象其中的每个节点,维护节点的状态信息。其结构如下:

type server struct {*eventDispatchername        stringpath        stringstate       string          // 每个节点总是处于以下状态的一种:follower、candidate、leadertransporter Transportercontext     interface{}currentTerm uint64          // Raft协议关键概念,每个term内都会产生一个新的leadervotedFor   stringlog        *Logleader     stringpeers      map[string]*Peer // raft中每个节点需要了解其他节点信息,尤其是leader节点mutex      sync.RWMutexsyncedPeer map[string]bool  // 对于leader来说,该成员记录了日志已经被sync到了哪些followerstopped           chan boolc                 chan *ev  // 当前节点的命令通道,所有的命令都通过该channel来传递electionTimeout   time.DurationheartbeatInterval time.Durationsnapshot *Snapshot// PendingSnapshot is an unfinished snapshot.// After the pendingSnapshot is saved to disk,// it will be set to snapshot and also will be// set to nil.pendingSnapshot *SnapshotstateMachine            StateMachinemaxLogEntriesPerRequest uint64connectionString stringroutineGroup sync.WaitGroup
}

log

log是Raft协议的核心,Raft使用日志来存储客户发起的命令,并通过日志内容的同步来维护多节点上状态的一致性。

// A log is a collection of log entries that are persisted to durable storage.
type Log struct {ApplyFunc   func(*LogEntry, Command) (interface{}, error)    // 日志被应用至状态机的方法,这个应该由使用raft的客户决定file        *os.File // 日志文件句柄path        string   // 日志文件路径entries     []*LogEntry  // 内存日志项缓存commitIndex uint64  // 日志提交点,小于该提交点的日志均已经被应用至状态机mutex       sync.RWMutexstartIndex  uint64  // 日志中起始日志项的indexstartTerm   uint64  // 日志中起始日志项的terminitialized bool
}

log entry

log entry是客户发起的command存储在日志文件中的内容

// 编码后的日志项包含Index、Term,原始Command的名称以及Command具体内容
type LogEntry struct {Index            *uint64 `protobuf:"varint,1,req" json:"Index,omitempty"`Term             *uint64 `protobuf:"varint,2,req" json:"Term,omitempty"`CommandName      *string `protobuf:"bytes,3,req" json:"CommandName,omitempty"`Command          []byte  `protobuf:"bytes,4,opt" json:"Command,omitempty"`XXX_unrecognized []byte  `json:"-"`
}// A log entry stores a single item in the log.
// LogEntry是日志项在内存中的描述结构,其最终存储在日志文件是经过protocol buffer编码以后的信息
type LogEntry struct {pb       *protobuf.LogEntryPosition int64 // position in the log file Position代表日志项存储在日志文件内的偏移log      *Logevent    *ev
}

Raft -【go一致性算法】相关推荐

  1. Paxos、Raft分布式一致性算法应用场景

    本文是Paxos.Raft分布式一致性最佳实践的第一篇文章,说明分布式一致性问题与分布式一致性算法的典型应用场景,帮助后面大家更好的理解Paxos.Raft等分布式一致性算法. 一.分布式一致性 (C ...

  2. 【转】分布式一致性算法:Raft 算法(Raft 论文翻译)

    编者按:这篇文章来自简书的一个位博主Jeffbond,读了好几遍,翻译的质量比较高,原文链接:分布式一致性算法:Raft 算法(Raft 论文翻译),版权一切归原译者. 同时,第6部分的集群成员变更读 ...

  3. RAFT 寻找一种易于理解的一致性算法(扩展版)

    摘要 Raft 是一种为了管理复制日志的一致性算法.它提供了和 Paxos 算法相同的功能和性能,但是它的算法结构和 Paxos 不同,使得 Raft 算法更加容易理解并且更容易构建实际的系统.为了提 ...

  4. Raft 一致性算法论文译文

    本篇博客为著名的 RAFT 一致性算法论文的中文翻译,论文名为<In search of an Understandable Consensus Algorithm (Extended Vers ...

  5. 分布式一致性算法:Raft 算法

    由于微信字数的限制,此处给出的并非全文,请拉到页面最下方点击阅读原文查看完整版. Raft 算法是可以用来替代 Paxos 算法的分布式一致性算法,而且 raft 算法比 Paxos 算法更易懂且更容 ...

  6. Raft 一致性算法论文

    本篇博客为著名的 RAFT 一致性算法论文的中文翻译,论文名为<In search of an Understandable Consensus Algorithm (Extended Vers ...

  7. Raft一致性算法论文

    本篇博客为著名的 RAFT 一致性算法论文的中文翻译,论文名为<In search of an Understandable Consensus Algorithm (Extended Vers ...

  8. 分布式一致性算法:Raft 算法(论文翻译)

    Raft 算法是可以用来替代 Paxos 算法的分布式一致性算法,而且 raft 算法比 Paxos 算法更易懂且更容易实现.本文对 raft 论文进行翻译,希望能有助于读者更方便地理解 raft 的 ...

  9. 分布式一致性算法Raft原理图释

    什么是分布式一致性算法Raft 分布式一致性算法Raft:指在分布式场景下实现集群数据同步的解决方案 掌握了这个算法,就可以较容易地处理绝大部分场景的容错和数据一致性需求 Raft三大角色 跟随者(F ...

  10. 【转】寻找一种易于理解的一致性算法(扩展版)

    摘要 Raft 是一种为了管理复制日志的一致性算法.它提供了和 Paxos 算法相同的功能和性能,但是它的算法结构和 Paxos 不同,使得 Raft 算法更加容易理解并且更容易构建实际的系统.为了提 ...

最新文章

  1. 2021fall Bloomberg校招
  2. cpythonjava解释xml_详解python使用lxml操作xml格式文件
  3. android authtype=1,【报Bug】plus.screen.lockOrientation在android里引起闪退
  4. 计算机协会科创部部长职责,学生会科创部工作计划
  5. .Net面试题(1)
  6. Qt编译过程中出现的问题
  7. python sin_Python sin() 函数
  8. geomesa hbase geoserver
  9. 雅客EXCEL(6)-通用表格格式、销售实际案例(总结之前的知识点)
  10. JStrom 入门(三) 上传jar文件并启动流程
  11. 构造函数的五种继承方法
  12. python字典和JSON格式的转换
  13. Leetcode每日一题:48.rotate-image(旋转图像)
  14. 如何在 Gitee 上使用 GPG
  15. Dropthings - Ajax Web Portal
  16. android模糊搜索文件,模糊搜索_八门神器教程|安卓八门神器怎么用图文教程__单机攻略_跑跑车单机游戏网...
  17. SM2246EN+闪迪15131
  18. linux的sssd服务,Linux sssd 认证
  19. 手淘推出“店铺二楼”
  20. python爬虫从入门到放弃,含案例分析,超详细讲解(一)

热门文章

  1. 在 Chrome 控制台可以玩的两个骚操作,你知道吗?
  2. mysql学习笔记--表操作
  3. 广发银行创新“智慧金融”打造“智慧城市”
  4. 超好用的webssh(支持秘钥登录)
  5. 使用Spring配合Junit进行单元测试的总结
  6. NOIP2011选择客栈[递推]
  7. ArcEngine由点生成TIN
  8. ProtocolBuffer for Objective-C 运行环境配置(真正测试过的)
  9. 南阳oj92--图像有用区域(Bfs)
  10. 【uTenux实验】写在开始实验之前