raft中集群成员变更
文章目录
- 1. raft集群变更再学习
- 2. 单阶段过度的风险分析
- 3. 两阶段过度的完整性分析
- 4. 集群变更时可能存在的其他问题
- 1. 新加入的节点没有日志
- 2. 集群领导人可能需要下线
- 3. 从```C-old```中移除的机器可能会干扰集群
1. raft集群变更再学习
最近再次看raft的中文文档的时候,前面都很顺畅,但是到集群变更这块儿感觉理解的还不是很透彻,于是回过头看了一下英文原文,又从网上参考了一些前辈大佬的文章。感觉有点思路了,故在此记录一下。
在原文上说的是,如果直接从Cold 切换到Cnew的话因为不能做到atomic的原子操作,所以可能会出现两个leader在同一个term当中并存的情况。但是对于具体的场景说的不够细致(也有可能是我的思考的还不够)
这里我尝试增强一些解释
- 每个节点node中都会有一个集群的cluster config (为了和论文中保持一致这里也叫C,之前的配置较
C-old
,新的叫C-new
) - 这里我们假设集群的变更是从3个节点(s1,s2,s3)增加到5个(s1,s2,s3,s4,s5), 在开始的时候leader为s1
- 在一个节点要加入cluster的时候,他会先向集群中的leader发起加入集群的请求,这个时候leader会将
C-old
发给对应的节点(这一点在论文中没有进行详述,只是我认为的一个合理方式) - 集群在选举的时候每个candinate是根据自己的cluster config来决定自己是否赢得了majority选票的(认为自己是leader)
- leader在进行log复制的时候也是根据自己的cluster config来决定是否达成了majority以便可以提交
- 这里的cluster config不需要等待commit就可以提交,也就是leader只要复制到了某个follower,follower就一定会使用新的config,不用等待leader提交之后
- 我们在这里为了简化问题,假设新加入的节点和当前集群中的节点是状态同步的(日志没有落后于其他节点),后面我们会单独针对这个情况补充。
2. 单阶段过度的风险分析
论文中说,如果直接从C-old
过度到C-new
会存在在集群中同时存在两个leader的风险,下面我们来尝试分析一下这个过程
- s4,s5,请求加入cluster,从leader上面得到了
C-old
- leader 在本地存储
C-new
,然后将这个日志复制到集群中的其他node - leader 在收到majority数量的复制成功应答后将
C-new
commit(这里的majority肯定是按照新的配置s1-s5来算的) - 集群使用新的
C-new
来管理日志提交
假如运行到第3步,有s1,s4,s5都是C-new
, s2,s3为C-old
,这个时候s1突然和其他节点发生了短时间的网络分区,导致集群进行了重新选举。
- 这个时候s2,s3可以通过选举得到一个leader,假设为s2,
- s1,s4,s5可以通过选举得到一个leader,假如为s4
那么在当前集群中就会同时存在两个leader,而且term是一致的,可能会引起数据混乱。这种应该就是论文中说的从Cold 切换到Cnew的话因为不能做到atomic的原子操作而导致的问题吧。
3. 两阶段过度的完整性分析
那么raft如何避免这个问题呢,他使用了被称为共同一致的两阶段提交方法,也就是通过两次日志的复制来实现从C-old
变成新的C-new
,英文称之为joint consensus
,这个过程的第一阶段复制的cluster config是C-(old,new)
, 这个时候要求使用cluster config的时候必须在C-old
和C-new
上都满足majority才行,在第一个阶段提交后才会再指向一个C-new
的复制和提交。
我们再来阐述一下这个过程,首先还是一个没有出错的过程
- s4,s5,请求加入cluster,从leader上面得到了
C-old
- leader在本地存储
C-(old,new)
,然后将这个日志复制到集群中的其他node - leader 在收到[
C-old
majority数量的复制成功] && [C-new
majority数量的复制成功] 应答后将C-(old,new)
commit - leader在完成3之后在本地存储一个新的配置
C-new
,然后将这个日志复制到集群中的node - leader在收到
C-new
majority数量的复制成功应答后将C-new
commit - 集群使用新的
C-new
来管理日志提交
接下来来重点分析一下在这里如果遭遇了异常应该怎么处理,证明不正确有时候很简单,就像上面的例子,我们只要举一个不安全的反例就行了,但是要想证明正确则可能比较困难,我们需要仔细考量每一个过程可能出现的异常:
- 同样的,假如运行到第3步,有s1,s4,s5都是
C-(old,new)
, s2,s3为C-old
,这个时候s1突然和其他节点发生了短时间的网络分区,导致集群进行了重新选举- 这个时候假如s2,s3可以通过选举得到一个leader,假设为s2, 那么s1,s4,s5虽然可以在
C-new
配置上达成一致,但是无法在C-old
上面达成一致(因为s2,s3不可能再给他们投票,每个term只有一次投票机会),所以也就不会出现两个leader的情况。 - 这个时候如果是s2,s3中的一个成为了leader,那么对应的
C-(old,new)
会被清除掉(强势leader的规则决定),s4,s5需要重新发起加入请求,等于重新走这个过程 - 假如s1,s4,s5中的一个称为了leader,那么就会继续完成第3步(让s2,s3中的至少一个复制
C-(old,new)
)接着往下走第4步。 - 在这整个过程中,无论是哪一个服务器当选leader,
C-new
都不会单独起作用,这句话非常重要,也就是是他保证了过度的平稳性。
- 这个时候假如s2,s3可以通过选举得到一个leader,假设为s2, 那么s1,s4,s5虽然可以在
- 假如运行到第4-5步之间,这个时候无论新旧配置对应的集群都复制了
C-(old,new)
设置。假如这个时候s1为leader, s1为c-new,s2,s3复制了C-(old,new)
, s4,s5任然为C-old
- 假如这个时候leader s1重启,这个时候,因为s4,s5发现cluster config中没有自己,也不会去竞选leader,即使竞选也会因为日志比较落后而失败
- 如果s2,s3中的任意一个当选leader,那肯定没有问题,因为要满足
C-(old,new)
,这个时候s1肯定没有机会再获得大多数的投票了, - 如果s1当选leader,那么s2,s3不管是否投票给s1,都会因为
C-(old,new)
中的C-new
的设置而不会当选leader,所以这个算是是安全的。
以上就是我对raft的集群配置变更的一些理解。同样,为了这篇文章的完整性,补充一下raft论文中提到的实际中面临的一些情况
4. 集群变更时可能存在的其他问题
1. 新加入的节点没有日志
第一个问题是,新的服务器可能初始化没有存储任何的日志条目。当这些服务器以这种状态加入到集群中,那么他们需要一段时间来更新追赶,这时还不能提交新的日志条目。为了避免这种可用性的间隔时间,Raft 在配置更新之前使用了一种额外的阶段,在这个阶段,新的服务器以没有投票权身份加入到集群中来(领导人复制日志给他们,但是不考虑他们是大多数)。一旦新的服务器追赶上了集群中的其他机器,重新配置可以像上面描述的一样处理。
2. 集群领导人可能需要下线
第二个问题是,集群的领导人可能不是新配置的一员(因为服务器问题可能需要先将这个leader服务停掉)。在这种情况下,领导人就会在提交了 C-new
日志之后退位(回到跟随者状态)。这意味着有这样的一段时间,领导人管理着集群,但是不包括他自己;他复制日志但是不把他自己算作是大多数之一。当 C-new
被提交时,会发生领导人过渡,因为这时是最早新的配置可以独立工作的时间点(将总是能够在 C-new
配置下选出新的领导人)。在此之前,可能只能从 C-old
中选出领导人。
3. 从C-old
中移除的机器可能会干扰集群
第三个问题是,移除后不在 C-new
中的服务器可能会扰乱集群。这些服务器将不会再接收到心跳,所以当选举超时,他们就会进行新的选举过程。他们会发送拥有新的任期号的请求投票 RPCs,这样会导致当前的领导人回退成跟随者状态。新的领导人最终会被选出来,但是被移除的服务器将会再次超时,然后这个过程会再次重复,导致整体可用性大幅降低。
为了避免这个问题,当服务器确认当前领导人存在时,服务器会忽略请求投票 RPCs。特别的,当服务器在当前最小选举超时时间内收到一个请求投票 RPC,他不会更新当前的任期号或者投出选票。这不会影响正常的选举,每个服务器在开始一次选举之前,至少等待一个最小选举超时时间。然而,这有利于避免被移除的服务器扰乱:如果领导人能够发送心跳给集群,那么他就不会被更大的任期号废黜。
参考
raft 中文
raft 英文
raft中集群成员变更相关推荐
- Raft 集群成员变更、日志压缩、客户端交互
Raft 集群成员变更.日志压缩.客户端交互 集群成员变更 在集群服务器发生变化时,不能一次性的把所有的服务器配置信息从老的替换为新的,因为,每台服务器的替换进度是不一样的,可能会导致出现双主的情况, ...
- HyperLedger FabricV2.3 Raft单机集群部署
目录 云主机配置 依赖环境配置 部署步骤 0.更新yum 1.安装golang 2.安装docker 3. 安装docker-compose 4. 安装git 5. 安装java 6. 防火墙配置 7 ...
- etcd v2文档(2) -- 客户端http请求管理集群成员api
为什么80%的码农都做不了架构师?>>> 列出成员 返回一个HTTP 200 OK响应代码和所有成员在etcd集群中的表示. Request GET /v2/members H ...
- elasticsearch中集群选举中的ping源码解析
在elasticsearch在选举中,节点之间的相互投票通过ping来实现. 其中的实现类为UnicastZenPing,在其构造方法中读取配置中的discovery.zen.ping.unicast ...
- es集群节点数和分片数关系_ElasticSeaerch(弹性搜索数据库)中集群、节点、副本和分片的区别...
简单总结下: 1.集群cluster: 集群顾名思义就是多个相同集群名称的es节点组合在一起.相当于一个集群就是一个班级,班级下面的学生就是节点. 如果只有一个节点在运行就称为单节点. 2.节点nod ...
- java中集群和分布式的区别_java 分布式与集群的区别和联系
java 分布式与集群的区别和联系 一.先说区别: 一句话:分布式是并联工作的,集群是串联工作的. 1.分布式是指将不同的业务分布在不同的地方. 而集群指的是将几台服务器集中在一起,实现同一业务. 分 ...
- Netapp集群模式变更
1.架构图如下 2.前提条件 FAS8200 升级到版本 9.7(目前建议的稳定版本) 新购FAS2750 降级到版本 9.7(目前建议的稳定版本) 3.物理线缆切换 新购FAS2750 集群口,分别 ...
- Redis - CLUSTER命令中集群管理命令详解
文章目录 导图 全文 导图 全文 都梳理好了,全文 请戳这里
- 了解Oracle RAC Brain Split Resolution集群脑裂协议
CSS工作原理 在理解脑裂(Brain Split)处理过程前,有必要介绍一下Oracle RAC Css(Cluster Synchronization Services)的工作框架: Oracle ...
最新文章
- Lomox0.2.0.1_Plugin_beta
- 【转载】WINCE物理和虚拟地址的问题
- Load和Initialize的往死了问是一种怎样的体验
- html背景过大,html – CSS – 背景大小:封面太大了
- 28. LAST() 函数
- php多商户限时抢购,GitHub - 617746883/thinkphp5.0_shop: 基于thinkphp5,多商户商城。积分商城、团购、秒杀、拍卖、夺宝等多插件(持续开发中)...
- 基于FPGA实现Aurora高速串行接口
- 路由协议的管理距离值
- opencv 实现图像形态学操作 膨胀和腐蚀 开闭运算 形态学梯度 顶帽和黑帽
- 【Codeforces Round #555 (Div. 3) G】Inverse of Rows and Columns【bitset优化暴力...】
- 西刺代理python_python网络爬虫实战——实时抓取西刺免费代理ip-Go语言中文社区...
- Json本地校验工具--HiJson
- 在多媒体计算机系统中图像的颜色是,图像量化位数越大,记录图像中每个像素点的颜色种类就越多。() - 试题答案网问答...
- mmdetection 绘制PR曲线
- 数据库实验1---创建数据库和表
- Postgresql计算月天数
- 英语NLP词汇类别列表
- 卡尔曼滤波最完整公式推导
- 程序员可以收藏的几个导航网站
- xcode和macos对应版本参考