网络不可能一直处于正常情况,因为Leader或者某个Follower有可能会崩溃,从而导致日志不能一直保持一致。因此存在以下三种情况:

(1)Follower缺失当前Leader上存在的日志条目。
(2)Follower存在当前Leader不存在的日志条目。(比如旧的Leader仅仅将AppendEntries RPC消息发送到一部分Follower就崩溃掉,然后新当选Leader的服务器恰好是没有收到该AppendEntries RPC消息的服务器)
(3)Follower即缺失当前Leader上存在的日志条目,也存在当前Leader不存在的日志条目

图中最上方是日志的索引号(1-12),每个方块代表一条日志信息,方块内数字代表该日志所处的任期号。

图中当前Leader(图中最上方一行日志代表当前Leader日志)处于任期号为8的时刻。以此图说明以上三种情况存在的原因:

Follower a、b(Follower崩溃没有接收到Leader发送的AppendEntries RPC消息)满足以上说明的第一种情况。
Follower c在任期为6的时刻,Followerd在任期为7的时刻为Leader,但没有完全完成日志的发送便崩溃了,满足以上说明的第三种情况。
Follower e在任期为4的时刻,Followerf在任期为2、3的时刻为Leader,但没有完全完成日志的发送便崩溃了,同时在其他服务器当选Leader时刻也没有接收到新的Leader发送的AppendEntries RPC消息,满足第三种情况。

日志不一致的解决方案

Leader通过强迫Follower的日志重复自己的日志来处理不一致之处。这意味着Follower日志中的冲突日志将被Leader日志中的条目覆盖。因此Leader必须找到与Follower最开始日志发生冲突的位置,然后删除掉Follower上所有与Leader发生冲突的日志,最后将自己的日志发送给Follower以解决冲突。

Leader不会删除或覆盖自己本地的日志条目

这些步骤从之前说到的日志的一致性检查开始。

当发生日志冲突时,Follower将会拒绝由Leader发送的AppendEntries RPC消息,并返回一个响应消息告知Leader日志发生了冲突。
Leader为每一个Follower维护一个nextIndex值。该值用于确定需要发送给该Follower的下一条日志的位置索引。(该值在当前服务器成功当选Leader后会重置为本地日志的最后一条索引号+1)
当Leader了解到日志发生冲突之后,便递减nextIndex值。并重新发送AppendEntries RPC到该Follower。并不断重复这个过程,一直到Follower接受该消息。
一旦Follower接受了AppendEntries RPC消息,Leader则根据nextIndex值可以确定发生冲突的位置,从而强迫Follower的日志重复自己的日志以解决冲突问题。

情况a:如上图,服务器S1在任期为2的时刻仅将日志<index:2,term:2>发送到了服务器S2便崩溃掉。

情况b:服务器S5在任期为3的时刻当选Leader(S5的计时器率先超时,递增任期号为3,高于服务器S3和S4,因此可以当选Leader),但没来得及发送日志便崩溃掉。

情况c:服务器S1在任期为4的时刻再次当选Leader(S1重启时,任期仍然为2,收到新的LeaderS5发送的心跳信息后更新任期为3,而在LeaderS5崩溃后,服务器S1为第一个计时器超时的,因此发起投票,任期更新为4,大于网络中其他服务器任期,成功当选Leader),同时将日志<index:2,term:2>发送到了服务器S2和S3,但还没有通知服务器对日志进行提交便崩溃掉。

情况d:情况(a->d)如果在任期为2时服务器S1作为Leader崩溃掉,S5在任期为3的时刻当选Leader,由于日志<index:2,term:2>还没有被复制到大部分服务器上,并没有被提交,所以S5可以通过自己的日志<index:2,term:3>覆盖掉日志<index:2,term:2>。

情况e:情况(a->e)如果在任期为2时服务器S1作为Leader,并将<index:2,term:2>发送到S2和S3,成功复制到大多数成员服务器上。并且成功提交了该日志,那么即便S1崩溃掉,S5也无法成功当选Leader,因为S5不具备网络中最新的已被提交的日志条目。

Raft算法系列教程4:日志不一致的解决的更多相关文章

  1. Raft算法系列教程1:Leader选举

    1.服务器的三种角色 Raft算法中服务器主要分为三种角色:Leader.Follower.Candidate,并且三种角色相互独立,也就是服务器在同一时间内只可能扮演其中一种角色. Leader:用 ...

  2. Raft算法系列教程3:日志复制

    1.日志复制的过程 Leader选出后,就开始接收客户端的请求.Leader把请求作为日志条目(Log entries)加入到它的日志中,然后并行的向其他服务器发起 AppendEntries RPC ...

  3. Raft算法系列教程2:状态机复制 (State Machine Replication)

    分区容错如何保证? 在分布式系统设计中,需要遵循CAP理论,如果我们要让一个服务具有容错能力,那么最常用最直接的办法就是让一个服务的多个副本同时运行在不同的节点上.但是,当一个服务的多个副本都在运行的 ...

  4. 手绘raft算法

    手绘raft算法 互联网技术窝 2019-04-07 12:06:05 在现实的分布式系统中,不能可能保证集群中的每一台机器都是100%可用可靠的,集群中的任何机器都可能发生宕机.网络连接等问题导致集 ...

  5. Fastify 系列教程一(路由和日志)

    介绍 Fastify是一个高度专注于以最少开销和强大的插件架构,为开发人员提供最佳体验的Web框架. 它受到了 Hapi 和 Express 的启发,是目前最快的 Node 框架之一. Fastify ...

  6. Fastify 系列教程一 (路由和日志)

    Fastify 系列教程: Fastify 系列教程一 (路由和日志) Fastify 系列教程二 (中间件.钩子函数和装饰器) Fastify 系列教程三 (验证.序列化和生命周期) Fastify ...

  7. 数据挖掘入门系列教程(二)之分类问题OneR算法

    数据挖掘入门系列教程(二)之分类问题OneR算法 数据挖掘入门系列博客:https://www.cnblogs.com/xiaohuiduan/category/1661541.html 项目地址:G ...

  8. 数据挖掘入门系列教程(三)之scikit-learn框架基本使用(以K近邻算法为例)

    数据挖掘入门系列教程(三)之scikit-learn框架基本使用(以K近邻算法为例) 简介 scikit-learn 估计器 加载数据集 进行fit训练 设置参数 预处理 流水线 结尾 数据挖掘入门系 ...

  9. 数据挖掘入门系列教程(四点五)之Apriori算法

    目录 数据挖掘入门系列教程(四点五)之Apriori算法 频繁(项集)数据的评判标准 Apriori 算法流程 结尾 数据挖掘入门系列教程(四点五)之Apriori算法 Apriori(先验)算法关联 ...

随机推荐

  1. 使用react终端运行npm start时报错

    npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! my-app@0.1.0 start: `react-scripts start` npm ERR ...

  2. python核心高级学习总结5--------python实现线程

    在代码实现上,线程的实现与进程的实现很类似,创建对象的格式都差不多,然后执行的时候都是用到start()方法,与进程的区别是进程是资源分配和调度的基本单位,而线程是CPU调度和分派的基本单位.其中多线 ...

  3. moviepy音视频剪辑:AudioClip帧处理时报TypeError: only size-1 arrays can be converted to Python scalar错

    ☞ ░ 前往老猿Python博文目录 ░ 一.环境 操作系统:win7 64位 moviepy:1.0.3 numpy:1.19.0 Python:3.7.2 二.应用代码及报错信息 程序代码 if ...

  4. mysql-installer-web-community和mysql-installer-communityl两个版本的区别

    mysql的官网上提供了两个mysql共享版本的安装,一个20M,一个373.4M.二者的区别是前者是联网安装,当安装时必须能访问互联网,后者是离线安装使用的,一般建议下载离线安装使用的版本. 学Py ...

  5. 第8.29节 使用MethodType将Python __setattr__定义的实例方法与实例绑定

    一. 引言 在<第7.14节Python类中的实例方法解析>介绍了使用"实例对象名.方法名 = MethodType(函数, 对象)"将动态定义的方法与实例进行绑定 在 ...

  6. PyQt(Python+Qt)学习随笔:QHeaderView.ResizeMode取值及含义

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 关于ResizeMode的使用请参考<PyQt(Python+Qt)学习随笔:QTableWi ...

  7. PyQt(Python+Qt)学习随笔:desktop的frameGeometry、frameSize、availableGeometry,screenGeometry

    frameGeometry:返回窗口相对于父窗口的几何形状的大小,包括窗口的框架,当窗口是顶级窗口时,返回的实际上是屏幕的大小: frameSize:返回窗口的几何形状的大小,包括窗口的框架,当窗口是 ...

  8. PHP代码审计分段讲解(9)

    22 弱类型整数大小比较绕过 <?php error_reporting(0); $flag = "flag{test}"; $temp = $_GET['password' ...

  9. flask加载配置文件的三种方法

    1.第一种方法也是我们最长用到的,包括我们项目中也是采用第一种的方法,加载配置文件 配置信息全部写在config.py里面,在主app.py的文件中写入 import config app.confi ...

  10. 使用postman发送http请求

    postman使用详解: http://gold.xitu.io/entry/57597a62a341310061337885 https://www.getpostman.com/docs/writ ...