解读Raft(四 成员变更)
将成员变更纳入到算法中是Raft易于应用到实践中的关键,相对于Paxos,它给出了明确的变更过程(实践的基础,任何现实的系统中都会遇到因为硬件故障等原因引起的节点变更的操作)。
显然,我们可以通过shutdown集群,然后变更配置后重启集群的方式达到成员变更的目的。但是这种操作会损失系统的可用性,同时会带来操作失误引起的风险。支持自动化配置,即配置可以在集群运行期间进行动态的变更(不影响可用性)显示是一个非常重要的特性。
Raft成员变更机制
在成员变更时,因为无法做到在同一个时刻使所有的节点从旧配置转换到新配置,那么直接从就配置向新配置切换就可能存在一个节点同时满足新旧配置的“超过半数”原则。
如下图,原集群由Server1、Server2、Server3,现在对集群做变更,增加Server4、Server5。如果采用直接从旧配置到新配置的切换,那么有一段时间存在两个不想交的“超过半数的集群”。

上图,中在中间位置Server1可以通过自身和Server2的选票成为Leader(满足旧配置下收到大多数选票的原则);Server3可以通过自身和Server4、Server5的选票成为Leader(满足新配置线,即集群有5个节点的情况下的收到大多数选票的原则);此时整个集群可能在同一任期中出现了两个Leader,这和协议是违背的。
为了保证安全性,Raft采用了一种两阶段的方式。
第一阶段称为joint consensus,当joint consensus被提交后切换到新的配置下。
joint consensus状态下:
- 日志被提交给新老配置下所有的节点
- 新旧配置中所有机器都可能称为Leader
- 达成一致(选举和提交)要在两种配置上获得超过半数的支持
具体的切换过程如下:
- Leader收到C-old到C-new的配置变更请求时,创建C-old-new的日志并开始复制给其他节点(和普通日志复制没有区别)
- Follower以最新的配置做决定(收到C-old-new后就以C-old-new来决定),Leader需要以已经提交的配置来做决定(即只有C-old-new复制到大多数节点后Leader才以这个配置做决定);这个时候处于一个共同决定的过程
- 之后提交C-new到所有节点,一旦C-new被提交,旧的配置就无所谓了

从上图可以看出,不存在一个阶段C-old和C-new可以同时根据自己的配置做出决定,所以不会出现本文开头描述的情况。
Review成员变更
如果当前的Leader不在C-new的配置中会怎么样(即当前的Leader是一个要被下线的节点)?
在C-old-new的状态下,Leader依旧可用;在C-new被commit之后Leader实际已经从集群中脱离,此时可以对Leader节点进行下线操作,而新集群则会在C-new的配置下重新选举出一个Leader。
如果在配置分发过程中Leader Crash了会怎么样?
这个问题要分为多种情况:1. C-new已经分发到超过半数节点、2. C-new还没分发到超过半数的节点
情况1:C-new已经分发到超过半数节点
集群开始重新选举,此时在C-new的规则下,旧节点(不存在新配置中的节点)不会赢得选举(因为他们要在C-old-new的情况下决定,但是拿不到C-new的选票),只有拿到C-new的节点可能成为Leader并继续下发C-new配置,流程恢复。
情况2:C-new还没分发到超过半数的节点
这种情况下,C-old-new和C-new的节点都可以成为Leader,但是无所谓,因为无论谁成为Leader,都能根据当前的配置继续完成后续流程(如果是C-new那么相当与完成了最终的配置,不在C-new的节点会因为没有心跳数据而失效)
旧节点下线造成的问题:旧节点收不到心跳触发选举,发送请求给C-old-new中的节点,是否会影响集群正常运行
Raft的处理方式:当节点确信有Leader存在时,不会进行投票(在Leader超时之前收到新的投票请求时不会提升term和投票)。且开始选举之前等待一个选举超时时间,这样在新Leader正常工作的情况下,不会受到旧节点的影响。
旧节点在发起选举前需要等待一段时间,那么这段时间新Leader可以发送心跳,这样就减少了影响。 对正常流程的影响不大。(Leader失效后要等一段时间,没有及时触发,然而本身这里就有一个判断失效的时间,好像影响不大;比如原先超时时间是10s,那么如果设置成5s,原策略下10s超时就是10s后开始选举,新策略下5s超时就是超时后再等5s再开始选举,影响就是超时时间变短)
新的服务器没有任何数据,加入进来进来怎么保证系统的可用性(这个时候新日志没办法Commit就没办法响应给客户端)?
新加入的节点需要时间复制数据,在这个过程完成之前,Raft采用以下机制来保证可用性: 新加入节点没有投票权(Leader复制日志给他们,但是不将他们考虑在机器数量里面——即在判断是否超过半数时不把这些节点考虑在内),直到这些节点的日志追上其他节点。
参考资料
论文:https://ramcloud.atlassian.net/wiki/download/attachments/6586375/raft.pdf
翻译:https://github.com/maemual/raft-zh_cn
动画演示:http://thesecretlivesofdata.com/raft/

解读Raft(四 成员变更)的更多相关文章
- etcd raft如何实现成员变更
成员变更在一致性协议里稍复杂一些,由于不同的成员不可能在同一时刻从旧成员组切换至新成员组,所以可能出现两个不相交的majority,从而导致同一个term出现两个leader,进而导致同一个index ...
- 解读Raft(一 算法基础)
最近工作中讨论到了Raft协议相关的一些问题,正好之前读过多次Raft协议的那paper,所以趁着讨论做一次总结整理. 我会将Raft协议拆成四个部分去总结: 算法基础 选举和日志复制 安全性 节点变 ...
- 【翻译】Raft 共识算法:集群成员变更
转载请注明出处:https://www.cnblogs.com/morningli/p/16770129.html 之前都在集群配置是固定的(参与共识算法的server集合)假设下讨论raft.在实践 ...
- AFNetworking 3.0 源码解读(四)之 AFURLResponseSerialization
本篇是AFNetworking 3.0 源码解读的第四篇了. AFNetworking 3.0 源码解读(一)之 AFNetworkReachabilityManager AFNetworking 3 ...
- Redis开源项目的终极杀手? ——CRUG解读Redis开源协议变更
引言: 数据库制造商 Redis Labs 本周将公司开发的Redis 模块从 AGPL 迁移到将 Apache v2.0 与 Commons Clause 相结合的许可证,对许可证涵盖的软件作了限制 ...
- Alamofire源码解读系列(四)之参数编码(ParameterEncoding)
本篇讲解参数编码的内容 前言 我们在开发中发的每一个请求都是通过URLRequest来进行封装的,可以通过一个URL生成URLRequest.那么如果我有一个参数字典,这个参数字典又是如何从客户端传递 ...
- 解读TCP 四种定时器
TCP 是提供可靠的传输层,它使用的方法之一就是确认从另一端收到的数据.但是数据和确认都可能会丢失.TCP 通过在发送时设置一个定时器来解决这个问题.如果当定时器溢出时还没收到确认,它就会重传该数据. ...
- 解读Raft(二 选举和日志复制)
Leader election Raft采用心跳机制来触发Leader选举.Leader周期性的发送心跳(如果有正常的RPC的请求情况下可以不发心跳)包保持自己Leader的角色(避免集群中其他节点认 ...
- 解读Raft(三 安全性)
前言 之前的两篇文章更多的是在描述Raft算法的正常流程,没有过多的去讨论异常场景. 而实际在分布式系统中,我们更多的都是在应对网络不可用.机器故障等异常场景,所以本篇来讨论一下Raft协议的安全性, ...
随机推荐
- Android系统剪切板
Android系统剪贴板 复制字符串到系统剪切板 /** * 复制文本到剪切板 * * @param text * @return */ @SuppressWarnings("depreca ...
- 【iOS 开发】基本 UI 控件详解 (UIButton | UITextField | UITextView | UISwitch)
博客地址 : http://blog.csdn.net/shulianghan/article/details/50051499 ; 一. UI 控件简介 1. UI 控件分类 UI 控件分类 : 活 ...
- C语言函数--atoi
在Java语言中,由于面向对象的思想,它对基本数据类型也进行了相应的封装,例如 int 就封装成了 Integer 类,这无疑会使我们的操作方便了许多,例如,有一个字符串,我想把它转换为i ...
- matlab中的sub2ind函数
在matlab中,矩阵的存储是按列优先,sub2ind函数将矩阵中指定元素的行列下标转换成存储的序号,即线性索引号.下面,我们举例子进行说明. 1 建立一个3*4*2的矩阵 rng(0,'twiste ...
- Github上怎么修改别人的项目并且提交给原作者!图文并茂!
Github上怎么修改别人的项目并且提交给原作者!图文并茂! 写这篇博客的初衷,是因为我的项目Only需要一些朋友一起参与进来,但是很多的Git都不是很熟练,其实版本控制这种东西没有什么难度的,只要稍 ...
- Dynamics CRM Microsoft SQL Server 指定的数据库具有更高的版本
在做NLB部署时遇到这么个问题,CRMAPP1安装的CRM版本是6.1已经打了SP1补丁,而在CRMAPP2上的CRM安装包是6.0版本,在选择连接现有部署后,最后一步检测就出了问题,如下图所示. 看 ...
- Android样式(style)和主题(theme)资源介绍-android学习之旅(五十六)
样式(style)资源 代码示例 <?xml version="1.0" encoding="utf-8"?> <LinearLayout x ...
- Miner.java 爬虫启动类
Miner.java 爬虫启动类 package com.iteye.injavawetrust.miner; import java.util.concurrent.ThreadPoolExecut ...
- 阿里云服务器实战(一) : 在Linux下Tomcat7下使用连接池
云服务器 的环境如下: Tomcat7+MySql5.6 一,如果自定义了程序的文件目录 , 下面的/alidata/xxx 就是自定义的目录 在Linux的Tomcat的server.xml里的Ho ...
- 2013 QCon北京演讲:跨终端的WebKit渲染机制
转载请注明原文地址:http://blog.csdn.net/milado_nju 1. 该演讲主要介绍WebKit的渲染机制的内部工作原理和一些新的技术,特别是针对不断出现的多种终端所做的一些努力. ...