Hands-On Hyperledger Fabric——Raft共识算法

本文参考Raft算法实现动画

在fabric1.4.1的版本中,提供了基于raft共识的raft排序服务。raft的模型可以容忍奔溃,如果有节点故障掉线可以正常运行。前提是要有大多数存活,也就是要保证1/2以上的节点个数正常运行。raft共识是“主从模型”,主节点通过动态选举决定,从节点是主节点的复制。raft排序服务比kafka排序服务易于设置和管理。并且raft的设计允许不同的组织贡献节点来共同组成排序服务。

kafka和zookeeper的设计不适用于大型网络。它们的设计是CFT模型,但局限于运行的比较紧密的主机上。也就是说,需要有一个组织专门运行kafka集群如果使用raft,每个组织可以贡献排序节点,共同组成排序服务,可以更好的去中心化

分布式系统的Raft算法

过去, Paxos一直是分布式协议的标准,但是Paxos难于理解,更难以实现,Google的分布式锁系统Chubby作为Paxos实现曾经遭遇到很多坑。

来自Stanford的新的分布式协议研究称为Raft,它是一个为真实世界应用建立的协议,主要注重协议的落地性和可理解性。

为了以容错方式达成一致,我们不可能要求所有服务器100%都达成一致状态,只要超过半数的大多数服务器达成一致就可以了,假设有N台服务器,N/2 +1 就超过半数,代表大多数了。

Paxos和Raft都是为了实现一致性共识这个目标,这个过程如同选举一样,参选者需要说服大多数选民(服务器)投票给他,一旦选定后就跟随其操作。Paxos和Raft的区别在于选举的具体过程不同。

在Raft中,任何时候一个服务器可以扮演下面角色之一:

  • Leader: 处理所有客户端交互,日志复制等,一般一次只有一个Leader。
  • Follower: 类似选民,完全被动。
  • Candidate: 候选者,可以被选为一个新的领导人。

Raft阶段分为两个首先是选举过程然后是数据同步过程(在选举出来的领导人带领进行正常操作,比如日志复制等)。

选举阶段

选举规则与过程

选举规则

  1. 每个节点在同一个Term(任期)下只能投一票
  2. Candidate的数据必须比自己的数据新或者相同,才可以投赞成票。
  3. 选举Term必须比当前Term要大
  4. 在发起选举的节点收到了集群中超过半数的选票后,在新的这个任期中,该集群的 Leader节点就是该节点,其他节点将切换成 Follower状态。

根据鸽巢原理,上面的条件可以知道,Candidate必然要比大半的节点数据更新才能当选Leader,而由于上一次日志同步需要过半的Follower确认,所以Candidate必然是最新的数据。

下面用图示展示这个过程:

  1. 任何一个服务器都可以成为一个候选者Candidate,它向其他服务器Follower发出要求选举自己的请求
    在这里插入图片描述2. 其他服务器同意了,发出OK。
    在这里插入图片描述
    注意如果在这个过程中,有一个Follower当机,没有收到请求选举的要求,因此候选者可以自己选自己,只要达到N/2 + 1 的大多数票,候选人还是可以成为Leader的。

  2. 这样这个候选者就成为了Leader领导人,它可以向选民也就是Follower们发出指令,比如进行日志复制。

在这里插入图片描述

  1. 以后通过心跳进行日志复制的通知

在这里插入图片描述

  1. 如果一旦这个Leader当机崩溃了,那么Follower中有一个成为候选者,发出邀票选举。
    在这里插入图片描述

  2. Follower同意后,其成为Leader,继续承担日志复制等指导工作:

在这里插入图片描述

选举的特殊情况

值得注意的是,整个选举过程是有一个时间限制的,如下图:

在这里插入图片描述

Splite Vote是因为如果同时有两个候选人向大家邀票,这时通过类似加时赛来解决,两个候选者在一段timeout比如300ms互相不服气的等待以后,因为双方得到的票数是一样的,一半对一半,那么在300ms以后,再由这两个候选者发出邀票,这时同时的概率大大降低,那么首先发出邀票的的候选者得到了大多数同意,成为领导者Leader,而另外一个候选者后来发出邀票时,那些Follower选民已经投票给第一个候选者,不能再投票给它,它就成为落选者了,最后这个落选者也成为普通Follower一员了。

所以为了两个Candidate的票数有差值,最好把节点的数量设置成为2n+1。
2n+1也是为了预防脑裂的情况。

网络分区情况的处理

在网络分区下,如果是2n+1的节点数量,必然有一个分区的节点数量是不够一半的,那一半分区的节点也就停止服务了,所以不存在脑裂的情况

由于该分区中节点数不足半数,所以无法选举出新的 Leader节点。待一段时间之后,该分区中又会出现某个节点的选举计时器超时,会再次发起新一轮的选举,循环往复,从而导致不断发起选举,Term号不断增长
在Raft协议中对这种情况有一个优化,当某个节点要发起选举之前,需要先进入一个叫作PreVote的状态,在该状态下,节点会先尝试连接集群中的其他节点,如果能够成功连接到半数以上的节点,才能真正发起新一轮的选举。

成员变更

成员变更的需求和领导⼈选举不⼀样,成员变更是主动的去切换节点(有时会去主动改变集群配置),所以希望能够不停机,对外提供服务。
如果贸然增加多个节点,可能会造成多个Leader的情况,造成脑裂。 最简单的解决办法是:成员变更⼀般是⼀次只添加⼀个节点,不要⼀次性加⼊多个

数据同步阶段

日志与状态机

Raft使⽤状态机的概念,包含了⽇志序列和数据状态机

  • ⽇志本质上就是⼀个数组,内部存储了⼀条⼀条的操作;
  • 在做⽇志同步的时候,通过按序执⾏⽇志操作,就可以还原相同的状态机的结果

由于一个Term内只有一个Leader,一个Leader下日志是有序的,所以通过Term+LogID就可以唯一索引一条日志。

下面以日志复制为例子说明Raft算法,假设Leader领导人已经选出,这时客户端发出增加一个日志的要求,比如日志是"sally":
在这里插入图片描述

  1. Leader要求Follower遵从他的指令,都将这个新的日志内容追加到他们各自日志中:

在这里插入图片描述

  1. 大多数follower服务器将日志写入磁盘文件后,确认追加成功,发出Commited Ok:

在这里插入图片描述

  1. 在下一个心跳heartbeat中,Leader会通知所有Follwer更新commited 项目。

对于每个新的日志记录,重复上述过程。

如果在这一过程中,发生了网络分区或者网络通信故障,使得Leader不能访问大多数Follwers了,那么Leader只能正常更新它能访问的那些Follower服务器,而大多数的服务器Follower因为没有了Leader,他们重新选举一个候选者作为Leader,然后这个Leader作为代表于外界打交道,如果外界要求其添加新的日志,这个新的Leader就按上述步骤通知大多数Followers,如果这时网络故障修复了,那么原先的Leader就变成Follower,在失联阶段这个老Leader的任何更新都不能算commit,都回滚,接受新的Leader的新的更新。

提交阶段的事务一致性问题

在Master的任期T3上,Client发送了y=6的请求给Master,所以这个时候:

  1. Master同步数据给B/C,B/C回复Master ACK
  2. Master收到半数ACK,⾃⼰提交数据,告知Client已经写⼊成功,并发送消息让其余节点也提交数据。

在第2步:“告知Client已经写⼊成功”和“发送消息让其余节点也提交数据”这两个步骤并不是原子的,如果两者其中⼀个失败,会有很⼤的问题:

  • 如果先告知Client成功,然后此时Master挂掉,没法通知Follower提交;这时候,Client以为插⼊成功了,实际上却没有。
  • 如果先通知Follower提交,那么如果Master挂掉,Client⽆法收到消息,会认为Master并没有存⼊成功,但实际上已经存了。

新上任的Leader如何处理前任未提交的数据?因为此时⽆法判断上任是否告知过 Client成功,可能告知后挂掉,也可能告知前就挂掉了

如何处理呢?

为了保证数据的⼀致性,这时候Leader节点只会追加⾃⼰的⽇志,不会删除或者覆盖⾃⼰的⽇志(注意这⾥不是说提交)。对于提交的⽅式, Leader节点在提交⾃⼰的⽇志的时候,顺便会提交旧⽇志,来保证Term最新。

如果前任Leader commit过后立刻挂了,其他至少过半节点中还包含着这条uncommited log,选出的新leader一定包含这条uncommited log,最终会协商把它也给apply掉。

注意:过半节点包含某一个log,就表示这个log被记录了,而不是leader commit后才表示的。

租约解决脑裂

refer:raft lease

总结

可以看出为什么Raft协议的读写都在主节点上了,因为不要求所有从节点与主节点的数据一致,所以对于从节点的读操作都会转发到主节点上,主节点的压力也会比较大。

当然如果数据对于消息不一致具备容忍性,也可以在Raft的follower节点上做读。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要基于Hyperledger Fabric测试环境添加共识,可以按照以下步骤进行操作: 1. 首先,确保已经在Centos系统下搭建了Hyperledger Fabric 2.4环境,并进入到Fabric Samples目录下的test-network目录中。 2. 接下来,需要下载Hyperledger Fabric CA的二进制文件,可以从官方发布的GitHub页面下载所需版本的二进制文件。根据提供的引用,你可以访问该链接下载hyperledger-fabric-ca-linux-amd64-1.5.2.tar.gz文件。 3. 解压下载的二进制文件,并将其复制到Fabric Samples目录下的bin目录中。 4. 进入test-network目录,在该目录中,你可以找到一个名为docker-compose-test-net.yaml的文件。此文件定义了Fabric网络的配置。 5. 打开docker-compose-test-net.yaml文件,你可以看到其中定义了Orderer节点和Peer节点的配置。在这个文件中,你可以添加共识算法的相关配置。 6. 根据你的需求,可以选择使用Solo共识算法或者Raft共识算法。如果要添加Solo共识算法,可以在Orderer节点的配置中添加以下行: ``` - CORE_PEER_GOSSIP_USELEADERELECTION=true - CORE_PEER_GOSSIP_ORGLEADER=false - CORE_PEER_GOSSIP_SKIPHANDSHAKE=true ``` 7. 如果要添加Raft共识算法,可以在Orderer节点的配置中添加以下行: ``` - ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=/var/hyperledger/orderer/tls/server.crt - ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=/var/hyperledger/orderer/tls/server.key - ORDERER_GENERAL_CLUSTER_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt] - ORDERER_GENERAL_CLUSTER_LISTENADDRESS=0.0.0.0:7050 - ORDERER_GENERAL_CLUSTER_SERVERCERTIFICATE=/var/hyperledger/orderer/tls/server.crt - ORDERER_GENERAL_CLUSTER_SERVERPRIVATEKEY=/var/hyperledger/orderer/tls/server.key - ORDERER_GENERAL_CLUSTER_TLS_ENABLED=true - ORDERER_GENERAL_CLUSTER_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt - ORDERER_GENERAL_CLUSTER_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key - ORDERER_GENERAL_CLUSTER_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt] - ORDERER_GENERAL_GENESISMETHOD=file - ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block - ORDERER_GENERAL_LOCALMSPID=OrdererMSP - ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp - ORDERER_GENERAL_TLS_ENABLED=true - ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key - ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt - ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt] ``` 8. 保存并关闭docker-compose-test-net.yaml文件。 9. 运行以下命令启动Fabric网络: ``` ./network.sh up ``` 10. 等待网络启动完成后,你就可以在Fabric网络中使用添加了共识算法的测试环境了。 请注意,以上步骤仅为添加共识算法的基本操作,具体的配置可能因版本或其他因素而有所不同。建议在进行任何更改之前,先仔细阅读Hyperledger Fabric的官方文档以获得更详细和准确的指导。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Hyperledger Fabric 2.x 环境搭建](https://blog.csdn.net/qq_15799869/article/details/125188251)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值