Raft成员变更的工程实践

简介: 成员变更是一致性系统实现绕不开的难题,对于提升运维能力以及服务可用性都有很大的帮助。 本文从Raft成员变更理论出发,介绍了Raft成员变更和单步成员变更的问题,其中包括Raft著名的Bug。 对于Raft成员变更的工程实现上需要考虑的问题,本文给出了一些工程实践经验。

1212.png

 

一  引言

 

成员变更是一致性系统实现绕不开的难题,对于提升运维能力以及服务可用性都有很大的帮助。

 

本文从Raft成员变更理论出发,介绍了Raft成员变更和单步成员变更的问题,其中包括Raft著名的Bug。

 

对于Raft成员变更的工程实现上需要考虑的问题,本文给出了一些工程实践经验。

 

二  Raft成员变更简介

 

分布式系统运行过程中节点经常会出现故障,需要支持节点的动态增加和删除。

 

成员变更是在集群运行过程中改变运行一致性协议的节点,如增加、减少节点、节点替换等。成员变更过程不能影响系统的可用性。

 

成员变更也是一个一致性问题,即所有节点对新成员达成一致。但是成员变更又有其特殊性,因为在成员变更的过程中,参与投票的成员会发生变化。

 

如果将成员变更当成一般的一致性问题,直接向Leader节点发送成员变更请求,Leader同步成员变更日志,达成多数派之后提交,各节点提交成员变更日志后从旧成员配置(Cold)切换到新成员配置(Cnew)。

 

因为各个节点提交成员变更日志的时刻可能不同,造成各个节点从旧成员配置(Cold)切换到新成员配置(Cnew)的时刻不同。可能在某一时刻出现Cold和Cnew中同时存在两个不相交的多数派,进而可能选出两个Leader,形成不同的决议,破坏安全性。

 

6e64c80155fce77e8f419677e74f971.png

图1 成员变更的某一时刻Cold和Cnew中同时存在两个不相交的多数派

 

如图1是3个节点的集群扩展到5个节点的集群,直接扩展可能会造成Server1和Server2构成老成员配置的多数派,Server3、Server4和Server5构成新成员配置的多数派,两者不相交从而可能导致决议冲突。
由于成员变更的这一特殊性,成员变更不能当成一般的一致性问题去解决。为了解决这个问题,Raft提出了两阶段的成员变更方法Joint Consensus。

 

1  Joint Consensus成员变更

 

Joint Consensus成员变更让集群先从旧成员配置Cold切换到一个过渡成员配置,称为联合一致成员配置(Joint Consensus),联合一致成员配置是旧成员配置Cold和新成员配置Cnew  的组合Cold,new,一旦联合一致成员配置Cold,new提交,再切换到新成员配置Cnew  。

 

微信图片_20210320144248.png

图2 Joint Consensus成员变更

 

Leader收到成员变更请求后,先向Cold和Cnew同步一条Cold,new日志,此后所有日志都需要Cold和Cnew两个多数派的确认。Cold,new日志在Cold和Cnew都达成多数派之后才能提交,此后Leader再向Cold和Cnew同步一条只包含Cnew的日志,此后日志只需要Cnew的多数派确认。Cnew日志只需要在Cnew达成多数派即可提交,此时成员变更完成,不在Cnew中的成员自动下线。

 

成员变更过程中如果发生Failover,老Leader宕机,Cold,new中任意一个节点都可能成为新Leader,如果新Leader上没有Cold,new日志,则继续使用Cold,Follower上如果有Cold,new日志会被新Leader截断,回退到Cold,成员变更失败;如果新Leader上有Cold,new日志,则继续将未完成的成员变更流程走完。

 

Joint Consensus成员变更比较通用且容易理解,但是实现比较复杂,之所以分为两个阶段,是因为对  与  的关系没有做任何假设,为了避免  和  各自形成不相交的多数派而选出两个Leader,才引入了两阶段方案。

 

如果增强成员变更的限制,假设Cold与Cnew任意的多数派交集不为空,Cold与Cnew就无法各自形成多数派,则成员变更就可以简化为一阶段。

 

2  单步成员变更
实现单步的成员变更,关键在于限制Cold与Cnew,使之任意的多数派交集不为空。方法就是每次成员变更只允许增加或删除一个成员。

 

3.png

图3 增加或删除一个成员

 

增加或删除一个成员时的情形,如图3所示,可以从数学上严格证明,只要每次只允许增加或删除一个成员,Cold与Cnew不可能形成两个不相交的多数派。因此只要每次只增加或删除一个成员,从Cold可直接切换到Cnew,无需过渡成员配置,实现单步成员变更。

 

单步成员变更一次只能变更一个成员,如果需要变更多个成员,可以通过执行多次单步成员变更来实现。

 

单步成员变更理论虽然简单,但却埋了很多坑,实际用起来并不是那么简单。

 

三  Raft单步成员变更的问题

 

Raft单步成员变更的问题,最著名的莫过于Raft著名的正确性问题,另外单步成员变更还有潜在的可用性问题。

 

1  Raft单步成员变更的正确性问题

 

Raft单步变更过程中如果发生Leader切换会出现正确性问题,可能导致已经提交的日志又被覆盖。Raft作者(Diego Ongaro)早在2015年就发现了这个问题,并且在Raft-dev详细的说明了这个问题[1]。

 

下面是一个Raft单步变更出问题的例子, 初始成员配置是abcd这4节点,节点u和V要加入集群, 如果中间出现Leader切换, 就会丢失已提交的日志:

 

4.png

图4 Raft单步成员变更的正确性问题

 

  • t0:节点abcd的成员配置为C0;
  • t1 :节点abcd在Term 0选出a为Leader,b和c为Follower;
  • t2:节点a同步成员变更日志Cu,只同步到a和u,未成功提交;
  • t3:节点a宕机;
  • t4:节点d在Term 1被选为Leader,b和c为Follower;
  • t5:节点d同步成员变更日志Cv,同步到c、d、V,成功提交;
  • t6:节点d同步普通日志E,同步到c、d、V,成功提交;
  • t7:节点d宕机;
  • t8:节点a在Term 2重新选为Leader,u和b为Follower;
  • t9:节点a同步本地的日志Cu给所有人,造成已提交的Cv和E丢失。

 

为什么会出现这样的问题呢?根本原因是上一任Leader的成员变更日志还没有同步到多数派就宕机了,新Leader一上任就进行成员变更,使用新的成员配置提交日志,之前上一任Leader重新上任之后可能形成另外一个多数派集合,产生脑裂,将已提交的日志覆盖,造成数据丢失。

 

Raft作者在发现这个问题之后,也给出了修复方法。修复方法很简单, 跟Raft的日志Commit条件类似:新任Leader必须在当前Term提交一条日志之后,才允许同步成员变更日志。也即Leader在当前Term还未提交日志之前,不允许同步成员变更日志。

 

按照这个修复方法,最简单的实现就是Leader上任后先提交一条no-op日志,然后再同步成员变更日志。这条no-op日志可以保证跟上一任Leader未提交的成员变更日志至少有一个节点交集,这样可以发现上一任Leader的日志是旧的,从而阻止上一任Leader重新选为Leader,进而阻止了脑裂的产生。

 

对应上面这个例子,就是L1当选Leader后必须先提交一条no-op日志,然后才能开始同步Cv和E,以便能发现L2的日志是旧的,从而阻止L2当选Leader。

 

另一种方法是使用Joint Consensus成员变更,没有这样的正确性问题。

 

2  Raft单步成员变更的可用性问题

 

单步成员变更每次只能增加或者减少一个成员,在做成员替换的时候需要分两次变更,第一次变更先将新成员加入进来,第二次变更再将老成员删除,中间如果如果网络分区,有可能会导致服务不可用。

1.png

考虑a、b、c三个成员部署在三个机房,现在因为a发生故障要将a替换为同机房的d。按照单步成员变更,abc要先变为abcd,再变为bcd。

 

2.png

中间经历的4节点abcd的状态, 有可能在出现二分的网络分区(ad|bc)时导致整个集群不可用。因为a与d位于同一机房,这种二分网络分区的情况在实际情况中还是不容忽视的。

 

3.png

 

怎么解决这个问题呢?一种方法是做成员替换的时候,先删除老成员,再加入新成员,即abc先变为bc,再变为bcd,这样可以避免abcd的状态。

 

4.png

 

另一种方法是使用Joint Consensus成员变更,abc先变为abc U bcd  ,再变为bcd,也不会经历abcd的状态。

 

四  Raft成员变更的工程实践

 

Raft成员变更的理论虽简单,但实际工程实现上还是有很多地方要考虑。因为Raft单步成员变更有正确性问题及可用性问题,工程上建议尽量使用Joint Consensus成员变更,这里主要讨论一些Joint Consensus成员变更工程实现上必须考虑的问题。

 

1  新成员先加入再同步数据还是先同步数据再加入

 

因为Raft需要严格保证顺序,而新成员上还没有任何数据,因此新成员加入集群后需要先同步数据才能正常工作。工程实现时就有两种选择,一种是让新成员先加入再同步数据,另一种是先给新成员同步数据,同步完成后再加入。这两种方式各有利弊。

11.png

表1 新成员先加入再同步数据和先同步数据再加入的优缺点

 

新成员先加入再同步数据,成员变更可以立即完成,并且因为只要大多数成员同意即可加入,甚至可以加入还不存在的成员,加入后再慢慢同步数据。但在数据同步完成之前新成员无法服务,但新成员的加入可能让多数派集合增大,而新成员暂时又无法服务,此时如果有成员发生Failover,很可能导致无法满足多数成员存活的条件,让服务不可用。因此新成员先加入再同步数据,简化了成员变更,但可能降低服务的可用性。

 

新成员先同步数据再加入,成员变更需要后台异步进行,先将新成员作为Learner角色加入,只能同步数据,不具有投票权,不会增加多数派集合,等数据同步完成后再让新成员正式加入,正式加入后可立即开始工作,不影响服务可用性。因此新成员先同步数据再加入,不影响服务的可用性,但成员变更流程复杂,并且因为要先给新成员同步数据,不能加入还不存在的成员。

 

2  成员变更日志使用什么配置

 

成员变更日志本身是为了改变成员配置,处在成员配置变更的临界点上,因此成员变更日志使用什么配置就很关键。

 

12.png

表2 Joint Consensus成员变更日志使用的成员配置

 

对于Joint Consensus成员变更,成员变更日志使用什么配置是确定的。Cold,new日志使用联合一致成员配置Cold,new,需要老成员配置Cold和新成员配置Cnew两个多数派确认才能提交,Cnew日志使用新成员配置Cnew,只需要新成员配置Cnew的多数派确认即可提交,但Cnew日志也会同步给老成员配置Cold,主要是为了让Cold中不在Cnew中的成员自动退出。

 

3  成员变更日志什么时候生效

 

成员变更通过成员变更日志来完成,让各成员对成员配置达成一致,但成员变更日志与普通日志不同,并不一定要等到提交后Apply生效。

 

13.png

表3 成员变更日志的生效时机

 

对于Joint Consensus成员变更,成员变更日志什么时候生效是确定的。在Leader上开始同步成员变更日志之前就需要生效,在Follower上成员变更日志持久化完成后就需要生效。成员变更日志还未提交就先生效了,因此在Leader切换后可能会回滚。

 

4  成员变更期间日志是否需要严格按序提交

 

考虑这样一种情况,成员变更减少了成员数量,进而减小了多数派集合,而更小的多数派更容易达成,造成成员变更之后的日志比之前的日志先达成多数派。

 

按照Raft论文中的commitIndex的推进算法:

 

If there exists an N such that N > commitIndex, a majority of matchIndex[i] ≥ N, and log[N].term == currentTerm:

 

set commitIndex = N

 

一条日志达成多数派就往前推进commitIndex至该日志,如果该日志之前有日志按照老成员配置还未达成多数派,也一并提交了。

 

这种情况是否会出问题呢?实际上并不会,因为成员变更之后,已经有日志使用新成员配置提交了,不在新成员配置中的节点不可能再当选Leader了,进而不会覆盖之前的日志,因此就算之前的日志按照老成员配置未达成多数派也可以安全的提交。

 

hashicorp raft的实现还是严格按序提交的,即只有前面的日志都达成多数派之后才能提交。

 

5  只有少数成员存活时怎么恢复服务

 

Raft只能在大多数成员存活的情况下才能正常工作,实际可能会遇到只有少数成员存活的情况,这个时候要怎么恢复服务14.png呢。

 

因为只有少数成员存活,已经不能达成多数派,不能写入数据,也不能做正常的成员变更。需要提供一个强制更改成员配置的接口,通过它设置每个成员的成员配置列表,便于从大多数成员故障中恢复。

 

比如只剩一个成员S1存活的时候,强制更改成员配置设置成员列表为{S1},这样形成一个只有S1的成员列表,让S1继续提供读写服务,后续再调度其他节点通过成员变更加入。通过强制修改成员列表,可以实现最大可用模式。

 

五  单步成员变更的工程实践

 

单步成员变更虽然不推荐在工程中使用,这里还是总结一下单步成员变更的一些工程实践,供研究讨论。

 

1  单步成员变更日志使用什么配置

 

对于单步成员变更,成员变更日志是使用新成员配置 还是老成员配置Cnew呢?实际上单步成员变更日志无论使用新成员配置Cold还是老成员配置Cnew都不会破坏Cold与Cnew的多数派至少有一个节点相交,因此单步成员变更日志既可以使用新成员配置Cold也可以使用老成员配置Cnew,两种方式各有利弊。

 

14.png

表4 单步成员变更日志使用老成员配置和使用新成员配置的优缺点

 

单步成员变更日志使用老成员配置Cold,可以避免单步成员变更的正确性问题,因此可以省略掉Leader上任后的no-op日志,同时在增加成员时可能只需要更小的多数派集合,但在减少成员时可能需要更大的多数派集合。

 

单步成员变更日志使用新成员配置Cnew,需要Leader上任后先提交一条no-op日志,以避免单步成员变更的正确性问题,同时在减少成员时可能只需要更小的多数派集合,但在增加成员时可能需要更大的多数派集合。

 

单步成员变更日志不管使用新成员配置还是老成员配置,最好都同步给新老成员配置中的所有成员,这样在增加成员时可以让新成员迟早收到通知,在减少成员时也可以让被删除的成员收到通知而自动退出。

 

Raft论文中单步成员变更日志使用新成员配置Cnew,etcd中单步成员变更日志使用老成员配置Cold。

 

2  单步成员变更日志什么时候生效

 

15.png

表5 单步成员变更日志的生效时机

 

对于单步成员变更,如果成员变更日志使用新成员配置,则与Joint Consensus成员变更一样,Leader上开始同步成员变更日志之前就需要生效,在Follower上成员变更日志持久化完成后就需要生效。如果成员变更日志使用老成员配置,理论上只需要在下一次成员变更开始之前生效即可,但实际为了让新加入的节点尽快开始服务,一般在成员变更日志提交后就生效。

 

Raft论文中单步成员变更日志使用新成员配置Cnew,本地持久化完成就生效;etcd中单步成员变更日志使用老成员配置Cold,提交后再生效。

 

六  总结

 

Raft提供了Joint Consensus成员变更和单步成员变更,极大的推动了成员变更在工程中的应用。本文总结了一些Raft单步成员变更的问题,以及成员变更的工程实践。Joint Consensus通用并且不容易踩坑,一阶段成员变更坑比较多。工程上建议尽量使用Joint Consensus成员变更。

原文链接

本文为阿里云原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/514008.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

No.1-Apache IoTDB 随笔 - Time Series DBMS 综述

简介: 这是一篇无法一口气读完的、文字过万[正文字数14390]的长文,这是一个无法中途不上厕所就看完的、关于时序数据库的视频[时长111分钟]分享的文字整理.. 大家好,很开心能够和大家一起交流时序数据库的相关的内容 首先还是简单自我介绍一…

overflowhidden把内容遮住了怎么办_图片有水印怎么办?不用PS,有这4招就够了

大家好,我是热衷解决问题的秋小叶!俗话说,文不如表,表不如图!图片是我们在做 PPT 时经常会使用到的高频元素。阿文老师曾经说过:但是,在没有接触到正确的搜图方法前,我们往往会在搜索…

谷歌云试图抢占SAP软件云市场;企业上云迎来“黄金时代”;IBM和SAP帮助金融机构加快采用云技术……...

NEWS本周新闻回顾调查表明80%的企业在云计算方面超支云计算优化服务商Virtana公司委托研究机构Arlington Research公司对350位云计算决策者进行的这项研究发现,82%的受访者表示其所在的公司在云计算方面的支出远远超过他们的需要。Market Research Future&#xff1…

Java设计模式-桥接模式

目录 一、手机操作问题 二、传统方法 三、基本介绍 四、原理类图 五、使用桥接模式解决手机问题 一、手机操作问题 现在对不同手机类型的不同品牌实现操作编程( 比如 : 开机、关机、上网,打电话等) , 如图: 二、传统方法 传统方案解决手机操作问题分…

Elasticsearch生态技术峰会 | Elasticsearch在清博大数据的应用与实践

简介: 开源最大的特征就是开放性,云生态则让开源技术更具开放性与创造性,Elastic 与阿里云的合作正是开源与云生态共生共荣的典范。值此合作三周年之际,我们邀请业界资深人士相聚云端,共话云上Elasticsearch生态与技术…

Elasticsearch生态技术峰会 | Elasticsearch在企查查的应用实践

简介: 开源最大的特征就是开放性,云生态则让开源技术更具开放性与创造性,Elastic 与阿里云的合作正是开源与云生态共生共荣的典范。值此合作三周年之际,我们邀请业界资深人士相聚云端,共话云上Elasticsearch生态与技术…

漫话:为什么计算机用补码存储数据?

作者 | 漫话编程来源 | 漫话编程我们知道,计算机只认识0和1,现实世界中的内容,无论是文字、音频、视频等等想要通过计算机存储、计算或者展示,都需要转换二进制。就像你刚刚唱的旋律,想要存储在计算机中也是要转成二进…

cad多个窗口并排显示_你早该这么做!并排查看Excel工作表其实一个小动作就搞定!...

特别福利:私信发送关键词【福利】,年度最全Office办公资源等你免费领哟~很多人都知道,有时在屏幕上并排查看起两个文件的内容,是一项非常顺畅和方便的操作——省去不少在不同窗口间来回切换的时间!当然,对于…

数据仓库如何实现湖仓一体数据分析?

简介: 随着云计算的普及和数据分析需求的扩大,数据湖数据仓库的湖仓一体分析能力成为下一代数据分析系统的核心能力。相对于数据仓库,数据湖在成本、灵活性、多源数据分析等多方面,都有着非常明显的优势。IDC发布的十项2021年中国…

Java应用全链路启动速度提升至15s,阿里云SAE能力再升级

简介: Java 作为一门面向对象编程语言,在性能方面的卓越表现独树一帜。但在高性能的背后,Java 的启动性能差也令人印象深刻,大家印象中的 Java 笨重、缓慢的印象也大多来源于此,高性能和快启动速度似乎有一些相悖。 近…

到底什么是“无源物联网”?

作者 | 小枣君来源 | 鲜枣课堂继Cat.1之后,2021年的物联网行业,又“喜提”了一个新的“风口”。这个“风口”的名字,叫做“无源物联网”。无源物联网,到底是个啥东东?它和现有的物联网技术之间,有什么区别&…

Gartner魔力象限到底有何“魔力”?

简介: Gartner魔力象限到底有何“魔力”?近日,Gartner发布了一系列最新魔力象限报告,在IT圈掀起了阵阵“龙卷风”,谁跻身全球第一阵营,谁跌出“领导者”象限,权威定调,众说纷纭&…

K8s 原生 Serverless 实践:ASK 与 Knative

简介: K8s 处在一个承上启下的位置,云原生用户使用 K8s 的目的是为了交付和管理应用,也包括灰度发布、扩容缩容等。但是对用户来说,实现这些能力,通过直接操作 K8s API 难免有些复杂。另外节省资源成本和弹性对于用户来…

react安装_前端大牛进阶---gt;React必会教程

一、背景介绍01React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设 Instagram 的网站。做出来以后,发现这套东西很好用,就在2013年5月开源…

透过 3.0 Preview 看 Dubbo 的云原生变革

简介: 做过微服务开发的开发者相信对 Dubbo 都不陌生,Dubbo 是一款能帮助我们快速解决微服务开发、通信以及流量治理的框架。相比于之前只限定在 Java 语言范围内,Dubbo 的多语言版本在这两年呈现了良好的发展势头,其中&#xff0…

扩展云存储边界,阿里云推出全球首个云定义存储产品

云计算正带来一场消除线上线下存储边界的革命。 9月22日,阿里云宣布云存储服务全面升级,包括性能大幅提升300%、时延降低70%的ESSD云盘;可兼容HDFS的数据湖存储OSS,同时推出一款全新产品“云定义存储”(Cloud Defined…

Go Mysql Driver 集成 Seata-Golang 解决分布式事务问题

简介: 2020 年 4 月,我们开始尝试实现 go 语言的分布式事务框架 Seata-Golang。众所周知,Seata AT 模式以无业务代码侵入的特点,被广大开发者推崇。Java 版 Seata AT 模式通过对 DataSource 数据源进行代理,在 sql 语句…

安装redis提示[test] error 2_技术干货分享:一次flask+redis的微服务实战

先说一下需求的场景,策划部门想做一个垂直领域的社区产品,类似与知乎那种,但受益人群是金融行业的从业人员。产品中有一个搜索问题的需求,搜索的问题去题库中进行模糊匹配,终端支持H5/APP/小程序,甚至是微信…

实现阿里云容器镜像服务反向访问代理

简介: 本文会先介绍镜像推送/拉取过程的交互逻辑来梳理需要代理的所有服务,再通过搭建一个公网 HTTPS 反向代理来访问容器镜像服务来向您展示多场景代理访问模式原理。 真实业务场景可能很复杂,因安全、合规、访问限制等原因可能需要&#x…

数字基础设施开源操作系统欧拉全新发布

在华为全联接2021上,面向数字基础设施的开源操作系统欧拉(openEuler)全新发布。欧拉操作系统可广泛部署于服务器、云计算、边缘计算、嵌入式等各种形态设备,应用场景覆盖IT(Information Technology)、CT&am…