解读Raft(二 选举和日志复制)
Leader election
Raft采用心跳机制来触发Leader选举。Leader周期性的发送心跳(如果有正常的RPC的请求情况下可以不发心跳)包保持自己Leader的角色(避免集群中其他节点认为没有Leader而开始选举)。
Follower在收到Leader或者Candidate的RPC请求的情况下一直保持Follower状态。而当一段时间内(election timeout)没有收到请求则认为没有Leader节点而出发选举流程。
选举流程如下:
- Follower递增自己的任期并设置为Candidate角色
- 投票给自己并且并发的给所有节点发送投票请求
- 保持Candidate状态直到:
- 同一个任期内获得大多数选票,成为Leader(一个节点在一个任期内只能给一个Candidate投票,任期相同则选票先到先得)并给其他节点发送心跳来保持自己的角色
- 收到其他节点的RPC请求,如果请求中的任期大于等于Candidate当前的任期,认为其他节点成为了Leader,自身转换为Follower;如果其他节点的任期小于自身的任期,拒绝RPC请求并保持Candidate角色
- 一段时间后仍旧没有Leader(可能是出现了平票的情况),则在选举超时后重新发起一轮选举(递增任期、发送投票请求)
为了避免平票的问题,同时在出现平票的情况后能快速解决,Raft的选举超时时间是在一个区间内随机选择的(150~300ms)。这样尽量把服务器选举时间分散到不同的时间,保证大多数情况下只有一个节点会发起选举。在平票的情况下,每个节点也会在一个随机时间后开始新一轮选举,避免可能出现的一直处于平票的情况。
Log replication
一旦Leader被选举出来后,Leader就开始为集群服务:处理所有的客户端请求并将数据复制到所有节点。
一旦日志被“安全”的复制,那么Leader将这个日志应用到自己的状态机并响应客户端。
如果有节点异常或网络异常,Leader会一直重试直到所有日志都会正确复制到所有节点(日志不允许有空洞,所以每个节点上的日志都是连续的,不能有因为失败引起的空洞)。
日志组织形式如上图,每个日志条目中包含可执行的指令、和日志被创建时的任期号,日志条目也包含了自己在日志中的位置,即index。一旦一个日志条目存在于大多数节点,那么该日志条目是committed的。
Raft算法保证所有committed的日志都是持久化的(日志需要在大多数节点上持久化之后再响应给客户端,这意味着每个Follower节点收到AppendEntry请求后需要持久化到日志之后再响应给Leader),且最终会被所有的状态机执行。
Raft算法保证了以下特性:
- 如果两个日志条目有相同的index和term,那么他们存储了相同的指令(即index和term相同,那么可定是同一条指令,就是同一个日志条目)
- 如果不同的日志中有两个日志条目,他们的index和term相同,那么这个条目之前的所有日志都相同
两条规则合并起来的含义:两个日志LogA、LogB,如果LogA[i].index=Log[i]B.index且LogA[i].term=Log[i].term,那么LogA[i]=Log[i]B,且对于任何n < i的日志条目,LogA[n]=LogB[n]都成立。(这个结论显而易见的可以从日志复制规则中推导出来)
一个新Leader被选举出来时,Follower可能是上图中的任何一种情况。
- (a)(b)可能还没复制到日志
- (c)(d)可能曾经是Leader,所有包含了多余的日志(这些日志可能被提交了,也可能没提交)
- (e)可能是成为Leader之后增加了一些日志,但是在Commit之前又编程了Follower角色,且还没有更新日志条目
- (f)可能是在任期2称为了Leader并追加了日志但是还没提交就Crash了,恢复之后在任期3又成了Leader并且又追加了日志
在Raft中,通过使用Leader的日志覆盖Follower的日志的方式来解决出现像上图的情况(强Leader)。Leader会找到Follower和自己想通的最后一个日志条目,将该条目之后的日志全部删除并复制Leader上的日志。详细过程如下:
- Leader维护了每个Follower节点下一次要接收的日志的索引,即nextIndex
- Leader选举成功后将所有Follower的nextIndex设置为自己的最后一个日志条目+1
- Leader将数据推送给Follower,如果Follower验证失败(nextIndex不匹配),则在下一次推送日志时缩小nextIndex,直到nextIndex验证通过
上面的方式显然可以通过一些方法进行优化来减少重试的次数,但是在Raft论文中对是否有必要进行优化提出了质疑,因为这种异常的情况很少出现。
解读Raft(二 选举和日志复制)的更多相关文章
- 图解Raft之日志复制
日志复制可以说是Raft集群的核心之一,保证了Raft数据的一致性,下面通过几张图片介绍Raft集群中日志复制的逻辑与流程: 在一个Raft集群中只有Leader节点能够接受客户端的请求,由Leade ...
- 解读Raft(一 算法基础)
最近工作中讨论到了Raft协议相关的一些问题,正好之前读过多次Raft协议的那paper,所以趁着讨论做一次总结整理. 我会将Raft协议拆成四个部分去总结: 算法基础 选举和日志复制 安全性 节点变 ...
- Raft 实现日志复制同步
Raft 实现日志复制同步 本篇文章以 John Ousterhout(斯坦福大学教授) 和 Diego Ongaro(斯坦福大学获得博士学位,Raft算法发明人) 在 Youtube 上的讲解视频及 ...
- 基于 raft 协议的 RocketMQ DLedger 多副本日志复制设计原理
目录 1.RocketMQ DLedger 多副本日志复制流程图 1.1 RocketMQ DLedger 日志转发(append) 请求流程图 1.2 RocketMQ DLedger 日志仲裁流程 ...
- MySQL复制(二)--基于二进制日志文件(binlog)配置复制
基础环境: 主库 从库 服务器IP地址 192.168.10.11 192.168.10.12 版本 5.7.24 5.7.24 已存在的数据库 mysql> show databases; ...
- Etcd中Raft日志复制的实现
Raft state of log commitIndex : A log entry is committed once the leader that created the entry has ...
- Raft算法系列教程3:日志复制
1.日志复制的过程 Leader选出后,就开始接收客户端的请求.Leader把请求作为日志条目(Log entries)加入到它的日志中,然后并行的向其他服务器发起 AppendEntries RPC ...
- Paxos 实现日志复制同步
Paxos 实现日志复制同步 本篇文章以 John Ousterhout(斯坦福大学教授) 和 Diego Ongaro(斯坦福大学获得博士学位,Raft算法发明人) 在 Youtube 上的讲解视频 ...
- Paxos 实现日志复制同步(Basic Paxos)
Paxos 实现日志复制同步 本篇文章以 John Ousterhout(斯坦福大学教授) 和 Diego Ongaro(斯坦福大学获得博士学位,Raft算法发明人) 在 Youtube 上的讲解视频 ...
随机推荐
- Spring Security 入门(1-4-1)Spring Security - 认证过程
理解时可结合一下这位老兄的文章:http://www.importnew.com/20612.html 1.Spring Security的认证过程 1.1.登录过程 - 如果用户直接访问登录页面 用 ...
- SQL Server 利用触发器对多表视图进行更新
其步骤就是:利用update操作触发器产生的2个虚拟表[inserted]用来存储修改的数据信息和[deleted]表,然后将对应的数据更新到对应数据表中的字段信息中: 1.首先创建3个表: a.信息 ...
- JSON(二)——JavaScript中js对象与JSON格式字符串的相互转换
首先我们来看一下js中JSON格式的字符串 var JSONStr1 = "{\"name\" : \"张三\"}"; 注意以下的写法不是j ...
- setInterval()使用时易疏忽的点
举个例子: 一道题目 这两个程序的区别就在于我向setInterval的参数一function写入了参数.这就是导致运行结果不尽如人意的原因. setInterval()方法可以接收三个参数,此参数会 ...
- PV 动态供给 - 每天5分钟玩转 Docker 容器技术(153)
前面的例子中,我们提前创建了 PV,然后通过 PVC 申请 PV 并在 Pod 中使用,这种方式叫做静态供给(Static Provision). 与之对应的是动态供给(Dynamical Provi ...
- vue2与vue1的区别
在前面的学习过程中我们已经对vue1有了一定的了解,下面我们来学习一下vue2,看一下vue1与vue2有什么区别. 区别1: 在vue2中使用v-for指令时它可以添加重复的内容,就像可以添加相同的 ...
- [转]linux查看日志文件内容命令
linux查看日志文件内容命令tail.cat.tac.head.echo tail -f test.log你会看到屏幕不断有内容被打印出来. 这时候中断第一个进程Ctrl-C, ---------- ...
- 玩一玩基于Token的 自定义身份认证+权限管理
使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录.大概的流程是这样的: 客户端使用用户名跟密码请求登录 服务端收到请求,去验证用户名与密码 验证成功后,服务端会签发一个 Toke ...
- 安装 WordPress 时一些常见问题
1)安装 WordPress 时,输入数据库信息后提交之后,却直接弹出一个空白页面 解决方法很简单,打开PHP的配置文件php.ini,查找max_execution_time,将这个参数改为max_ ...
- LoggerOne
LoggerOne 一个高效.简约.灵活高性能的遵循 PSR-3 的 PHP 日志类库实现. 特性 天然的缓存特性(Logger实例属性),延迟批量写入. 安装&使用 Install $ co ...