解读Raft(一 算法基础)
最近工作中讨论到了Raft协议相关的一些问题,正好之前读过多次Raft协议的那paper,所以趁着讨论做一次总结整理。
我会将Raft协议拆成四个部分去总结:
算法基础
选举和日志复制
安全性
节点变更
这是第一篇:《解读Raft(一 算法基础)》
什么是RAFT
分布式系统除了提升整个体统的性能外还有一个重要特征就是提高系统的可靠性。
提供可靠性可以理解为系统中一台或多台的机器故障不会使系统不可用(或者丢失数据)。
保证系统可靠性的关键就是多副本(即数据需要有备份),一旦有多副本,那么久面临多副本之间的一致性问题。
一致性算法正是用于解决分布式环境下多副本之间数据一致性的问题的。
业界最著名的一致性算法就是大名鼎鼎的Paxos(Chubby的作者曾说过:世上只有一种一致性算法,就是Paxos)。但Paxos是出了名的难懂,而Raft正是为了探索一种更易于理解的一致性算法而产生的。
Raft is a consensus algorithm for managing a replicated log.
Raft是一种管理复制日志的一致性算法。
它的首要设计目的就是易于理解,所以在选主的冲突处理等方式上它都选择了非常简单明了的解决方案。
Raft将一致性拆分为几个关键元素:
Leader选举
日志复制
安全性
Raft算法
所有一致性算法都会涉及到状态机,而状态机保证系统从一个一致的状态开始,以相同的顺序执行一些列指令最终会达到另一个一致的状态。

以上是状态机的示意图。所有的节点以相同的顺序处理日志,那么最终x、y、z的值在多个节点中都是一致的。
算法基础
角色
Raft通过选举Leader并由Leader节点负责管理日志复制来实现多副本的一致性。
在Raft中,节点有三种角色:
Leader:负责接收客户端的请求,将日志复制到其他节点并告知其他节点何时应用这些日志是安全的
Candidate:用于选举Leader的一种角色
Follower:负责响应来自Leader或者Candidate的请求
角色转换如下图所示:

所有节点初始状态都是Follower角色
超时时间内没有收到Leader的请求则转换为Candidate进行选举
Candidate收到大多数节点的选票则转换为Leader;发现Leader或者收到更高任期的请求则转换为Follower
Leader在收到更高任期的请求后转换为Follower
任期
Raft把时间切割为任意长度的任期,每个任期都有一个任期号,采用连续的整数。

每个任期都由一次选举开始,若选举失败则这个任期内没有Leader;如果选举出了Leader则这个任期内有Leader负责集群状态管理。
算法
状态
| 状态 | 所有节点上持久化的状态(在响应RPC请求之前变更且持久化的状态) |
|---|---|
| currentTerm | 服务器的任期,初始为0,递增 |
| votedFor | 在当前获得选票的候选人的 Id |
| log[] | 日志条目集;每一个条目包含一个用户状态机执行的指令,和收到时的任期号 |
| 状态 | 所有节点上非持久化的状态 |
|---|---|
| commitIndex | 最大的已经被commit的日志的index |
| lastApplied | 最大的已经被应用到状态机的index |
| 状态 | Leader节点上非持久化的状态(选举后重新初始化) |
|---|---|
| nextIndex[] | 每个节点下一次应该接收的日志的index(初始化为Leader节点最后一个日志的Index + 1) |
| matchIndex[] | 每个节点已经复制的日志的最大的索引(初始化为0,之后递增) |
AppendEntries RPC
用于Leader节点复制日志给其他节点,也作为心跳。
| 参数 | 解释 |
|---|---|
| term | Leader节点的任期 |
| leaderId | Leader节点的ID |
| prevLogIndex | 此次追加请求的上一个日志的索引 |
| prevLogTerm | 此次追加请求的上一个日志的任期 |
| entries[] | 追加的日志(空则为心跳请求) |
| leaderCommit | Leader上已经Commit的Index |
prevLogIndex和prevLogTerm表示上一次发送的日志的索引和任期,用于保证收到的日志是连续的。
| 返回值 | 解释 |
|---|---|
| term | 当前任期号,用于Leader节点更新自己的任期(应该说是如果这个返回值比Leader自身的任期大,那么Leader需要更新自己的任期) |
| success | 如何Follower节点匹配prevLogIndex和prevLogTerm,返回true |
接收者实现逻辑
返回false,如果收到的任期比当前任期小
返回false,如果不包含之前的日志条目(没有匹配prevLogIndex和prevLogTerm)
如果存在index相同但是term不相同的日志,删除从该位置开始所有的日志
追加所有不存在的日志
如果leaderCommit>commitIndex,将commitIndex设置为commitIndex = min(leaderCommit, index of last new entry)
RequestVote RPC
用于Candidate获取选票。
| 参数 | 解释 |
|---|---|
| term | Candidate的任期 |
| candidateId | Candidate的ID |
| lastLogIndex | Candidate最后一条日志的索引 |
| lastLogTerm | Candidate最后一条日志的任期 |
| 参数 | 解释 |
|---|---|
| term | 当前任期,用于Candidate更新自己的任期 |
| voteGranted | true表示给Candidate投票 |
接收者的实现逻辑
返回false,如果收到的任期比当前任期小
如果本地状态中votedFor为null或者candidateId,且candidate的日志等于或多余(按照index判断)接收者的日志,则接收者投票给candidate,即返回true
节点的执行规则
所有节点
如果commitIndex > lastApplied,应用log[lastApplied]到状态机,增加lastApplied
如果RPC请求或者响应包含的任期T > currentTerm,将currentTerm设置为T并转换为Follower
Followers
响应来自Leader和Candidate的RPC请求
如果在选举超时周期内没有收到AppendEntries的请求或者给Candidate投票,转换为Candidate角色
Candidates
转换为candidate角色,开始选举:
递增currentTerm
给自己投票
重置选举时间
发送RequestVote给其他所有节点
如果收到了大多数节点的选票,转换为Leader节点
如果收到Leader节点的AppendEntries请求,转换为Follower节点
如果选举超时,重新开始新一轮的选举
Leaders
一旦选举完成:发送心跳给所有节点;在空闲的周期内不断发送心跳保持Leader身份
如果收到客户端的请求,将日志追加到本地log,在日志被应用到状态机后响应给客户端
如果对于一个跟随者,最后日志条目的索引值大于等于 nextIndex,那么:发送从 nextIndex 开始的所有日志条目:
如果成功:更新相应跟随者的 nextIndex 和 matchIndex
如果因为日志不一致而失败,减少 nextIndex 重试
如果存在一个满足N > commitIndex的 N,并且大多数的matchIndex[i] ≥ N成立,并且log[N].term == currentTerm成立,那么令commitIndex等于这个N

解读Raft(一 算法基础)的更多相关文章
- 解读Raft(三 安全性)
前言 之前的两篇文章更多的是在描述Raft算法的正常流程,没有过多的去讨论异常场景. 而实际在分布式系统中,我们更多的都是在应对网络不可用.机器故障等异常场景,所以本篇来讨论一下Raft协议的安全性, ...
- Raft 一致性算法论文译文
本篇博客为著名的 RAFT 一致性算法论文的中文翻译,论文名为<In search of an Understandable Consensus Algorithm (Extended Vers ...
- Levenberg-Marquardt算法基础知识
Levenberg-Marquardt算法基础知识 (2013-01-07 16:56:17) 转载▼ 什么是最优化?Levenberg-Marquardt算法是最优化算法中的一种.最优化是寻找使 ...
- 分布式系统一致性问题和Raft一致性算法
一致性问题 一致性算法是用来解决一致性问题的,那么什么是一致性问题呢? 在分布式系统中,一致性问题(consensus problem)是指对于一组服务器,给定一组操作,我们需要一个协议使得最后它们的 ...
- [转载] 一致性问题和Raft一致性算法
原文: http://daizuozhuo.github.io/consensus-algorithm/ raft 协议确实比 paxos 协议好懂太多了. 一致性问题 一致性算法是用来解决一致性问题 ...
- 腾讯2017年暑期实习生编程题【算法基础-字符移位】(C++,Python)
算法基础-字符移位 时间限制:1秒 空间限制:32768K 题目: 小Q最近遇到了一个难题:把一个字符串的大写字母放到字符串的后面,各个字符的相对位置不变,且不能申请额外的空间. 你能帮帮小Q吗? ...
- raft共识算法
raft共识算法 分布式一致性问题 如果说,服务器只有一个节点,那么,要保证一致性,没有任何问题,因为所有读写都在一个节点上发生.那如果server端有2个.3个甚至更多节点,要怎么达成一致性呢?下面 ...
- 算法基础_递归_求杨辉三角第m行第n个数字
问题描述: 算法基础_递归_求杨辉三角第m行第n个数字(m,n都从0开始) 解题源代码(这里打印出的是杨辉三角某一层的所有数字,没用大数,所以有上限,这里只写基本逻辑,要符合题意的话,把循环去掉就好) ...
- 毕业设计预习:SM3密码杂凑算法基础学习
SM3密码杂凑算法基础学习 术语与定义 1 比特串bit string 由0和1组成的二进制数字序列. 2 大端big-endian 数据在内存中的一种表示格式,规定左边为高有效位,右边为低有效位.数 ...
随机推荐
- codevs 3342 绿色通道
codevs 3342 绿色通道 http://codevs.cn/problem/3342/ 难度等级:黄金 题目描述 Description <思远高考绿色通道>(Green Pass ...
- Unix下zfs文件系统重组RAID-5后可以这样恢复
存储做的RAID-5, SCSI硬盘,操作系统是FreeBSD,文件系统是zfs.本案例共有12块硬盘,11块硬盘里有数据,1块硬盘是热备盘.其中第6块数据硬盘出现故障,重组时需要将其剔除. 物理盘: ...
- 推荐net开发cad入门阅读代码片段
转载自 Cad人生 的博客 链接:http://www.cnblogs.com/cadlife/articles/2668158.html 内容粘贴如下,小伙伴们可以看看哦. using Syst ...
- JAVA_SE基础——62.String类的构造方法
下面我先列出初学者目前用到的构造方法 String 的构造方法: String() 创建一个空内容 的字符串对象. String(byte[] bytes) 使用一个字节数组构建一个字 ...
- 快速搭建fabric-v1.1.0的chaincode开发环境
本文参考了fabric官方文档:http://hyperledger-fabric.readthedocs.io/en/latest/peer-chaincode-devmode.html?highl ...
- linux下的Shell编程(6)case和select
第一个,除了if语句之外,Shell Script中也有类似C语言中多分支结构的case语句,它的语法是: case var in pattern 1 ) - ;; pattern 2 ) - ;; ...
- Python/MySQL(三、pymysql使用)
Python/MySQL(三.pymysql使用) 所谓pymysql就是通过pycharm导入pymysql模块进行远程连接mysql服务端进行数据管理操作. 一.在pycharm中导入pymysq ...
- Asp.Net Core 2.0 项目实战(8)Core下缓存操作、序列化操作、JSON操作等Helper集合类
本文目录 1. 前沿 2.CacheHelper基于Microsoft.Extensions.Caching.Memory封装 3.XmlHelper快速操作xml文档 4.Serializatio ...
- C#:多进程开发,控制进程数量
正在c#程序优化时,如果多线程效果不佳的情况下,也会使用多进程的方案,如下: System.Threading.Tasks.Task task=System.Threading.Tasks.Task. ...
- iOS 同一个workspace下创建多个项目编程
在iOS开发中,相关联的多个项目可能会放在同一个workspace下进行开发,那习惯了一个项目在一个工作空间下的同学该怎么快速开撸呢? 只需要三步而已! 第一步,先用Xcode在目标目录下创建一个wo ...