Raft算法系列教程3:日志复制
1、日志复制的过程
Leader选出后,就开始接收客户端的请求。Leader把请求作为日志条目(Log entries)加入到它的日志中,然后并行的向其他服务器发起 AppendEntries RPC 复制日志条目。当这条日志被复制到大多数服务器上,Leader将这条日志应用到它的状态机并向客户端返回执行结果。
客户端的每一个请求都包含被复制状态机执行的指令。Leader把这个指令作为一条新的日志条目添加到日志中,然后并行发起 RPC 给其他的服务器,让它们复制这条信息。假如这条日志被安全的复制,Leader就应用这条日志到自己的状态机中,并返回给客户端。如果Follower宕机或者运行缓慢或者丢包,Leader会不断的重试,直到所有的Follower最终都复制了所有的日志条目。
2、日志的组成
日志由有序编号(log index)的日志条目组成。每个日志条目包含它被创建时的任期号(term)和用于状态机执行的命令。如果一个日志条目被复制到大多数服务器上,就被认为可以提交(commit)了。
上图显示,共有 8 条日志,提交了 7 条。提交的日志都将通过状态机持久化到磁盘中,防止宕机。
3、日志复制的详细介绍
当Leader接收到由客户端发送的请求(请求中包含可以被复制状态机执行的命令)时,Leader将会把该请求作为新的内容添加到日志中(任期号为当前Leader所处的任期号,索引号为当前Leader本地存储的日志集合中的日志的最高索引号加1)。
备注:Leader在当前任期内最多只能创建一个给定索引号的日志(即不可能在一个任期内创建两个以上的具有相同索引的日志条目)
然后将该日志通过AppendEntries RPC消息发送到网络中其他的服务器(以下简称Follower),从而复制该日志。
在网络中Follower接收到该日志消息后则会返回复制成功的回复。
在Leader接收到网络中大部分的Follower的成功复制的回复之后,Leader便认为该日志可以被提交。此时Leader将会同时做三件事:
(1)将该日志应用到Leader本地的复制状态机
(2)向所有Follower发送消息通知所有接收到该日志的Follower将该日志进行提交,然后应用到各自本地的复制状态机
(3)将执行结果通知客户端
当该日志消息成功在网络中大部分Follower本地的复制状态机执行过后,则可认为该日志已被提交。在当前日志被提交的过程中,如果Leader先前的某些日志还没有被提交,则将会一同提交。
而网络中有些Follower可能由于网络状态原因反应缓慢或者崩溃,那么Leader将会无限次地尝试重复发送AppendEntries RPC消息到该Follower。直到成功为止。
4、日志的一致性检查
如上所述,Follower在接收到AppendEntries RPC消息后则会返回复制成功的回复。实际上在接收到消息后会首先进行日志的一致性检查(正常情况下Leader与Follower的日志会保持一致,所以一致性检查不会失败),一致性检查内容如下:
在Leader创建AppendEntries RPC消息时,消息中将会包含当前日志之前日志条目的任期号与索引号。
Follower在接受到AppendEntries RPC消息后,将会检查之前日志的任期号与索引号是否匹配到。如果匹配到则说明和Leader之前的日志是保持一致的,否则,如果没有匹配则会拒绝AppendEntries RPC消息。
一致性检查是一个归纳的过程。正常情况下,网络中第一条日志一定满足日志的一致性检查,然后第二条日志中包含第一条日志的任期号与索引号,所以只要Leader与Follower的第一条日志保持一致,那么第二条日志也会满足一致性检查,从而之后的每一条日志都会满足一致性检查。
从而得出了日志匹配属性:
(1)如果两个不同的日志实体具有相同的索引和任期号,那么它们存储有相同的命令。
(2)如果两个不同的日志实体具有相同的索引和任期号,则所有先前条目中的日志都相同。(由一致性检查结果得出)
Raft算法系列教程3:日志复制的更多相关文章
- Raft算法系列教程1:Leader选举
1.服务器的三种角色 Raft算法中服务器主要分为三种角色:Leader.Follower.Candidate,并且三种角色相互独立,也就是服务器在同一时间内只可能扮演其中一种角色. Leader:用 ...
- Raft算法系列教程2:状态机复制 (State Machine Replication)
分区容错如何保证? 在分布式系统设计中,需要遵循CAP理论,如果我们要让一个服务具有容错能力,那么最常用最直接的办法就是让一个服务的多个副本同时运行在不同的节点上.但是,当一个服务的多个副本都在运行的 ...
- Raft算法系列教程4:日志不一致的解决
网络不可能一直处于正常情况,因为Leader或者某个Follower有可能会崩溃,从而导致日志不能一直保持一致.因此存在以下三种情况: (1)Follower缺失当前Leader上存在的日志条目.(2 ...
- 解读Raft(二 选举和日志复制)
Leader election Raft采用心跳机制来触发Leader选举.Leader周期性的发送心跳(如果有正常的RPC的请求情况下可以不发心跳)包保持自己Leader的角色(避免集群中其他节点认 ...
- 分布式一致性算法:Raft 算法(论文翻译)
Raft 算法是可以用来替代 Paxos 算法的分布式一致性算法,而且 raft 算法比 Paxos 算法更易懂且更容易实现.本文对 raft 论文进行翻译,希望能有助于读者更方便地理解 raft 的 ...
- 【转】分布式一致性算法:Raft 算法(Raft 论文翻译)
编者按:这篇文章来自简书的一个位博主Jeffbond,读了好几遍,翻译的质量比较高,原文链接:分布式一致性算法:Raft 算法(Raft 论文翻译),版权一切归原译者. 同时,第6部分的集群成员变更读 ...
- Paxos 实现日志复制同步
Paxos 实现日志复制同步 本篇文章以 John Ousterhout(斯坦福大学教授) 和 Diego Ongaro(斯坦福大学获得博士学位,Raft算法发明人) 在 Youtube 上的讲解视频 ...
- Paxos 实现日志复制同步(Basic Paxos)
Paxos 实现日志复制同步 本篇文章以 John Ousterhout(斯坦福大学教授) 和 Diego Ongaro(斯坦福大学获得博士学位,Raft算法发明人) 在 Youtube 上的讲解视频 ...
- Raft 实现日志复制同步
Raft 实现日志复制同步 本篇文章以 John Ousterhout(斯坦福大学教授) 和 Diego Ongaro(斯坦福大学获得博士学位,Raft算法发明人) 在 Youtube 上的讲解视频及 ...
随机推荐
- shardingsphere与分布式事务
rt https://blog.csdn.net/l1028386804/article/details/79769043 https://blog.csdn.net/qq_20387013/arti ...
- guava中的SettableFuture分析
当缓存中没有要找的数据时,则要从数据库中去查询,而当并发量比较大时可能会击穿数据库,所以guava cache对同一值的查询做了合并请求的处理.其中就用到了SettableFuture,类似一把锁,只 ...
- moviepy音视频剪辑:使用VideoFileClip、AudioFileClip和write_videofile、write_audiofile进行音视频的加载和输出
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 老猿学5G博文目录 一.概述 在本地进行音视频处理时,首先要从视频文件 ...
- 第8.22节 Python案例详解:重写 “富比较”方法控制比较逻辑
一. 案例说明 本节定义一个小汽车的类Car,类中包括车名carname.百公里油耗oilcostper100km.价格price三个属性.然后实现__lt__.__gt__.__le__.__ge_ ...
- 第二十六章、containers容器类部件QToolBox工具箱详解
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 容器部件就是可以在部件内放置其他部件的部件,在Qt Designer中可以使用的容器部件有 ...
- 安装pyspider出现的问题
本文来自微信公众号:coder_xiaobu,欢迎关注 一.安装pyspider pip install pyspider 二.启动 pyspider all 三.安装中出现的问题处理 安装的时候出现 ...
- pytorch实战(一)hw1——李宏毅老师作业1
任务描述:利用前9小时数据,预测第10小时的pm2.5的数值,回归任务 kaggle地址:https://www.kaggle.com/c/ml2020spring-hw1 训练集为: 12个月*20 ...
- Java基础学习之数据类型、基础语法与数组(3)
目录 1.数据类型 1.1.基本数据类型 1.2.引用数据类型 1.3.自动装箱与拆箱 2.基础语法 2.1.标识符 2.2.修饰符 2.2.1.访问控制修饰符 2.2.2.非访问控制修饰符 2.3. ...
- SpringMVC拦截html页面访问
在 web.xml 配置文件 原本的前端控制器后面加一个 servlet-mapping 即可简单解决 虽能解决 html 访问的问题,但不清楚是否对后面的操作产生何种影响 <servlet&g ...
- bootstrap 扩展参数
后台接受的参数形式 前端加载bootstrap时做的处理