Fabric的Raft共识机制

Fabric的Raft共识机制
在fabric1.4.1的版本中,提供了基于Raft共识的Raft排序服务。Raft的模型可以容忍奔溃,如果有节点故障掉线可以正常运⾏。前提是要有⼤多数存活,也就是要保证1/2以上的节点个数正常运⾏。Raft共识是“主从模型”,主节点通过动态选举决定,从节点是主节点的复制。Raft排序服务⽐kafka排序服务易于设置和管理。并且Raft的设计允许不同的组织贡献节点来共同组成排序服务。
Raft算法是⼀种为了管理复制⽇志的⼀致性算法。为了提升可理解性,Raft将⼀致性算法分解成了⼏个关键模块,例如领导者选举、⽇志复制和安全性。同时它通过实施⼀个更强的⼀致性来减少需要考虑的状态的数量。Raft 算法还包括⼀个新的机制来允许集成员的动态改变,它利⽤重叠的⼤多数来保证安全性。
Raft算法的特性:
领导者:和其他⼀致性算法相⽐,Raft使⽤⼀种更强的领导能⼒形式。⽐如,⽇志条⽬只从领导者发送给其他的服务器。这种⽅式简化了对复制⽇志的管理并且使得Raft算法更加易于理解。
领导选举:Raft算法使⽤⼀个随机计时器来选举领导者。这种⽅式只是在任何⼀致性算法都必须实现的⼼跳机制上增加了⼀点机制。在解决冲突的时候会更加简单快捷。
成员关系调整:Raft使⽤⼀种共同⼀致的⽅法来处理集成员变换的问题,在这种⽅法下,处于调整过程中的两种不同的配置集中⼤多数机器会有重叠,这就使得集在成员变换的时候依然可以继续⼯作。
设计原理
Raft算法通过选举⼀个领导者,然后给予他全部的管理复制⽇志的责任来实现⼀致性。领导者从客户端接收⽇志条⽬,把⽇志条⽬复制到其他服务器上,并且在保证安全性的同时告诉其他的服务器应⽤⽇志条⽬到他们的状态机中。拥有⼀个领导者⼤⼤简化了对复制⽇志的管理。例如,领导者可以决定新的⽇志条⽬需要放在⽇志中的什么位置⽽不需要和其他服务器商议,并且数据都从领导者流向其他服务器。⼀个领导者可以宕机,可以和其他服务器失去连接,这时⼀个新的领导者会被选举出来。
旋转座椅通过领导者的⽅式,Raft 将⼀致性问题分解成了三个相对独⽴的⼦问题:
领导选举:当现存的领导者宕机的时候,⼀个新的领导者需要被选举出来。座便轮椅
⽇志复制:领导者必须从客户端接收⽇志,然后复制到集中的其他节点,并且强制要求其他节点的⽇志和⾃⼰保持同步。
安全性:在 Raft 中安全性的关键是状态机安全:如果有任何的服务器节点已经应⽤了⼀个确定的⽇志
条⽬到它的状态机中,那么其他服务器节点不能在同⼀个⽇志索引位置应⽤⼀个不同的指令。
⼀个Raft集包含若⼲个服务器节点;通常是5个,这允许整个系统容忍 2 个节点的失效。在任何时刻,每⼀个服务器节点都处于这三个状态之⼀:领导⼈、跟随者或者候选⼈。
在通常情况下,系统中只有⼀个领导⼈并且其他的节点全部都是跟随者。跟随者都是被动的:他们不会发送任何请求,只是简单的响应来⾃领导者或者候选⼈的请求。领导⼈处理所有的客户端请求(如果⼀个客户端和跟随者联系,那么跟随者会把请求重定向给领导⼈)。第三种状态,候选⼈,是⽤来选举新领导⼈时使⽤。
跟随者只响应来⾃其他服务器的请求。如果跟随者接收不到消息,那么他就会变成候选⼈并发起⼀次选举。获得集中⼤多数选票的候选⼈将成为领导者。在⼀个任期内,领导⼈⼀直都会是领导⼈直到⾃⼰宕机了。
Raft把时间分割成任意长度的任期,任期⽤连续的整数标记。每⼀段任期从⼀次选举开始,⼀个或者多个候选⼈尝试成为领导者。如果⼀个候选⼈赢得选举,然后他就在接下来的任期内充当领导⼈的职责。在某些情况下,⼀次选举过程会造成选票的⽠分。在这种情况下,这⼀任期会以没有领导⼈结束;⼀个新的任期(和⼀次新的选举)会很快重新开始。Raft保证了在⼀个给定的任期内,最多只有⼀个领导者。
不同的服务器节点可能多次观察到任期之间的转换,但在某些情况下,⼀个节点也可能观察不到任何⼀次选举或者整个任期全程。任期在Raft算法中充当逻辑时钟的作⽤,这会允许服务器节点查明⼀些过期的信息⽐如陈旧的领导者。每⼀个节点存储⼀个当前任期号,这⼀编号在整个时期内单调的增长。当服务器之间通信的时候会交换当前任期号;如果⼀个服务器的当前任期号⽐其他⼈⼩,那么他会更新⾃⼰的编号到较⼤的编号值。如果⼀个候选⼈或者领导者发现⾃⼰的任期号过期了,那么他会⽴即恢复成跟随者状态。如果⼀个节点接收到⼀个包含过期的任期号的请求,那么他会直接拒绝这个请求。
Raft算法中服务器节点之间通信使⽤远程过程调⽤(RPCs),并且基本的⼀致性算法只需要两种类型的 RPCs。请求投票(RequestVote) RPCs 由候选⼈在选举期间发起,然后附加条⽬(AppendEntries)RPCs 由领导者发起,⽤来复制⽇志和提供⼀种⼼跳机制。当服务器没有及时的收到 RPC 的响应时,会进⾏重试,并且他们能够并⾏的发起 RPCs 来获得最佳的性能。
领导⼈选举
Raft使⽤⼀种⼼跳机制来触发领导⼈选举。当服务器程序启动时,他们都是跟随者⾝份。⼀个服务器节点继续保持着跟随者状态只要他从领导⼈或者候选者处接收到有效的 RPCs。领导者周期性的向所有跟随者发送⼼跳包(即不包含⽇志项内容的附加⽇志项 RPCs)来维持⾃⼰的权威。如果⼀个跟随
者在⼀段时间⾥没有接收到任何消息,也就是选举超时,那么他就会认为系统中没有可⽤的领导者,并且发起选举以选出新的领导者。
要开始⼀次选举过程,跟随者先要增加⾃⼰的当前任期号并且转换到候选⼈状态。然后他会并⾏的向集中的其他服务器节点发送请求投票的 RPCs 来给⾃⼰投票。候选⼈会继续保持着当前状态直到以下三件事情之⼀发⽣:
他⾃⼰赢得了这次的选举;
其他的服务器成为领导者;
⼀段时间之后没有任何⼀个获胜的⼈。
当⼀个候选⼈从整个集的⼤多数服务器节点获得了针对同⼀个任期号的选票,那么他就赢得了这次选举并成为领导⼈。每⼀个服务器最多会对⼀个任期号投出⼀张选票,按照先来先服务的原则。要求⼤多数选票的规则确保了最多只会有⼀个候选⼈赢得此次选举。⼀旦候选⼈赢得选举,他就⽴即成为领导⼈。然后他会向其他的服务器发送⼼跳消息来建⽴⾃⼰的权威并且阻⽌新的领导⼈的产⽣。
在等待投票的时候,候选⼈可能会从其他的服务器接收到声明它是领导⼈的附加⽇志项 RPC。如果这个领导⼈的任期号(包含在此次的RPC中)不⼩于候选⼈当前的任期号,那么候选⼈会承认领导⼈合
法并回到跟随者状态。 如果此次 RPC 中的任期号⽐⾃⼰⼩,那么候选⼈就会拒绝这次的 RPC 并且继续保持候选⼈状态。
第三种事情的结果是候选⼈既没有赢得选举也没有输:如果有多个跟随者同时成为候选⼈,那么选票可能会被⽠分以⾄于没有候选⼈可以赢得⼤多数⼈的⽀持。当这种情况发⽣的时候,每⼀个候选⼈都会超时,然后通过增加当前任期号来开始⼀轮新的选举。然⽽,没有其他机制的话,选票可能会被⽆限的重复⽠分。
Raft算法使⽤随机选举超时时间的⽅法来确保很少会发⽣选票⽠分的情况,就算发⽣也能很快的解决。为了阻⽌选票起初就被⽠分,选举超时时间是从⼀个固定的区间(例如 150-300 毫秒)随机选择。这样可以把服务器都分散开以⾄于在⼤多数情况下只有⼀个服务器会选举超时;然后他赢得选举并在其他服务器超时之前发送⼼跳包。同样的机制被⽤在选票⽠分的情况下。每⼀个候选⼈在开始⼀次选举的时候会重置⼀个随机的选举超时时间,然后在超时时间内等待投票的结果;这样减少了在新的选举中另外的选票⽠分的可能性。
⽇志复制
⼀旦⼀个领导⼈被选举出来,他就开始为客户端提供服务。客户端的每⼀个请求都包含⼀条被复制状态机执⾏的指令。领导⼈把这条指令作为⼀条新的⽇志条⽬附加到⽇志中去,然后并⾏的发起附加条
⽬ RPCs 给其他的服务器,让他们复制这条⽇志条⽬。当这条⽇志条⽬被安全的复制(下⾯会介绍),领导⼈会应⽤这条⽇志条⽬到它的状态机中然后把执⾏的结果返回给客户端。如果跟随者崩溃或者运⾏缓慢,再或者⽹络丢包,领导⼈会不断的重复尝试附加⽇志条⽬ RPCs (尽管已经回复了客户端)直到所有的跟随者都最终存储了所有的⽇志条⽬。
领导⼈来决定什么时候把⽇志条⽬应⽤到状态机中是安全的;这种⽇志条⽬被称为已提交。Raft 算法保证所有已提交的⽇志条⽬都是持久化的并且最终会被所有可⽤的状态机执⾏。在领导⼈将创建的⽇志条⽬复制到⼤多数的服务器上的时候,⽇志条⽬就会被提交。同时,领导⼈的⽇志中之前的所有⽇志条⽬也都会被提交,包括由其他领导⼈创建的条⽬,同时他也展⽰了这种提交的定义是安全的。领导⼈跟踪了最⼤的将会被提交的⽇志项的索引,并且索引值会被包含在未来的所有附加⽇志 RPCs (包括⼼跳包),这样其他的服务器才能最终知道领导⼈的提交位置。⼀旦跟随者知道⼀条⽇志条⽬已经被提交,那么他也会将这个⽇志条⽬应⽤到本地的状态机中(按照⽇志的顺序)。
我们设计了 Raft 的⽇志机制来维护⼀个不同服务器的⽇志之间的⾼层次的⼀致性。这么做不仅简化了系统的⾏为也使得更加可预计,同时他也是安全性保证的⼀个重要组件。Raft 维护着以下的特性:
如果在不同的⽇志中的两个条⽬拥有相同的索引和任期号,那么他们存储了相同的指令。
如果在不同的⽇志中的两个条⽬拥有相同的索引和任期号,那么他们之前的所有⽇志条⽬也全部相同。
第⼀个特性来⾃这样的⼀个事实,领导⼈最多在⼀个任期⾥在指定的⼀个⽇志索引位置创建⼀条⽇志条⽬,同时⽇志条⽬在⽇志中的位置也从来不会改变。第⼆个特性由附加⽇志 RPC 的⼀个简单的⼀致性检查所保证。在发送附加⽇志 RPC 的时候,领导⼈会把新的⽇志条⽬紧接着之前的条⽬的索引位置和任期号包含在⾥⾯。如果跟随者在它的⽇志中不到包含相同索引位置和任期号的条⽬,那么他就会拒绝接收新的⽇志条⽬。⼀致性检查就像⼀个归纳步骤:⼀开始空的⽇志状态肯定是满⾜⽇志匹配特性的,然后⼀致性检查保护了⽇志匹配特性当⽇志扩展的时候。因此,每当附加⽇志 RPC 返回成功时,领导⼈就知道跟随者的⽇志⼀定是和⾃⼰相同的了。
在正常的操作中,领导⼈和跟随者的⽇志保持⼀致性,所以附加⽇志 RPC 的⼀致性检查从来不会失败。然⽽,领导⼈崩溃的情况会使得⽇志处于不⼀致的状态(⽼的领导⼈可能还没有完全复制所有的⽇志条⽬)。这种不⼀致问题会在领导⼈和跟随者的⼀系列崩溃下加剧。图 7展⽰了跟随者的⽇志可能和新的领导⼈不同的⽅式。跟随者可能会丢失⼀些在新的领导⼈中有的⽇志条⽬,他也可能拥有⼀些领导⼈没有的⽇志条⽬,或者两者都发⽣。丢失或者多出⽇志条⽬可能会持续多个任期。
在 Raft 算法中,领导⼈处理不⼀致是通过强制跟随者直接复制⾃⼰的⽇志来解决了。这意味着在跟随者中的冲突的⽇志条⽬会被领导⼈的⽇志覆盖。
要使得跟随者的⽇志进⼊和⾃⼰⼀致的状态,领导⼈必须到最后两者达成⼀致的地⽅,然后删除从
那个点之后的所有⽇志条⽬,发送⾃⼰的⽇志给跟随者。所有的这些操作都在进⾏附加⽇志 RPCs 的⼀致性检查时完成。领导⼈针对每⼀个跟随者维护了⼀个 nextIndex,这表⽰下⼀个需要发送给跟随者的⽇志条⽬的索引地址。当⼀个领导⼈刚获得权⼒的时候,他初始化所有nextIndex 值为⾃⼰的最后⼀条⽇志的index加1。如果⼀个跟随者的⽇志和领导⼈不⼀致,那么在下⼀次的附加⽇志 RPC 时的⼀致性检查就会失败。在被跟随者拒绝之后,领导⼈就会减⼩ nextIndex 值并进⾏重试。最终 nextIndex 会在某个位置使得领导⼈和跟随者的⽇志达成⼀致。当这种情况发⽣,附加⽇志RPC 就会成功,这时就会把跟随者冲突的⽇志条⽬全部删除并且加上领导⼈的⽇志。⼀旦附加⽇志 RPC 成功,那么跟随者的⽇志就会和领导⼈保持⼀致,并且在接下来的任期⾥⼀直继续保持。
如果需要的话,算法可以通过减少被拒绝的附加⽇志 RPCs 的次数来优化。例如,当附加⽇志 RPC 的请求被拒绝的时候,跟随者可以包含冲突的条⽬的任期号和⾃⼰存储的那个任期的最早的索引地址。借助这些信息,领导⼈可以减⼩ nextIndex 越过所有那个任期冲突的所有⽇志条⽬;这样就变成每个任期需要⼀次附加条⽬ RPC ⽽不是每个条⽬⼀次。在实践中,我们⼗分怀疑这种优化是否是必要的,因为失败是很少发⽣的并且也不⼤可能会有这么多不⼀致的⽇志。苹果灯
通过这种机制,领导⼈在获得权⼒的时候就不需要任何特殊的操作来恢复⼀致性。他只需要进⾏正常的操作,然后⽇志就能⾃动的在回复附加⽇志 RPC 的⼀致性检查失败的时候⾃动趋于⼀致。领导⼈从来不会覆盖或者删除⾃⼰的⽇志。
⽇志复制机制展⽰出了Raft算法的⼀致性特性:Raft 能够接受,复制并应⽤新的⽇志条⽬只要⼤部分的机器是⼯作的;在通常的情况下,新的⽇志条⽬可以在⼀次 RPC 中被复制给集中的⼤多数机器;并且单个的缓慢的跟随者不会影响整体的性能。
安全性
如果服务器已经在某个给定的索引值应⽤了⽇志条⽬到⾃⼰的状态机⾥,那么其他的服务器不会应⽤⼀个不⼀样的⽇志到同⼀个索引值上。在⼀个服务器应⽤⼀条⽇志条⽬到他⾃⼰的状态机中时,他的⽇志必须和领导⼈的⽇志,在该条⽬和之前的条⽬上相同,并且已经被提交。现在我们来考虑在任何⼀个服务器应⽤⼀个指定索引位置的⽇志的最⼩任期;⽇志完全特性保证拥有更⾼任期号的领导⼈会存储相同的⽇志条⽬,所以之后的任期⾥应⽤某个索引位置的⽇志条⽬也会是相同的值。因此,状态机安全特性是成⽴的。
跟随者和候选⼈崩溃
跟随者和候选⼈崩溃后的处理⽅式⽐领导⼈要简单的多,并且他们的处理⽅式是相同的。如果跟随者或者候选⼈崩溃了,那么后续发送给他们的 RPCs 都会失败。Raft 中处理这种失败就是简单的通过⽆限的重试;如果崩溃的机器重启了,那么这些 RPC 就会完整的成功。如果⼀个服务器在完成了⼀个 RPC,但是还没有响应的时候崩溃了,那么在他重新启动之后就会再次收到同样的请求。Raft 的 RP尺寸测量
Cs 都是幂等的,所以这样重试不会造成任何问题。例如⼀个跟随者如果收到附加⽇志请求但是他已经包含了这⼀⽇志,那么他就会直接忽略这个新的请求。
空气加温器
时间和可⽤性
Raft 的要求之⼀就是安全性不能依赖时间:整个系统不能因为某些事件运⾏的⽐预期快⼀点或者慢⼀点就产⽣了错误的结果。但是,可⽤性(系统可以及时的响应客户端)不可避免的要依赖于时间。例如,如果消息交换⽐服务器故障间隔时间长,候选⼈将没有⾜够长的时间来赢得选举;没有⼀个稳定的领导⼈,Raft 将⽆法⼯作。
领导⼈选举是 Raft 中对时间要求最为关键的⽅⾯。Raft 可以选举并维持⼀个稳定的领导⼈,只要系统满⾜下⾯的时间要求:⼴播时间(broadcastTime) << 选举超时时间(electionTimeout) << 平均故障间隔时间(MTBF)
在这个不等式中,⼴播时间指的是从⼀个服务器并⾏的发送 RPCs 给集中的其他服务器并接收响应的平均时间;选举超时时间就是在
5.2 节中介绍的选举的超时时间限制;然后平均故障间隔时间就是对于⼀台服务器⽽⾔,两次故障之间的平均时间。⼴播时间必须⽐选举超时时间⼩⼀个量级,这样领导⼈才能够发送稳定的⼼跳消息来
阻⽌跟随者开始进⼊选举状态;通过随机化选举超时时间的⽅法,这个不等式也使得选票⽠分的情况变得不可能。选举超时时间应该要⽐平均故障间隔时间⼩上⼏个数量级,这样整个系统才能稳定的运⾏。当领导⼈崩溃后,整个系统会⼤约相当于选举超时的时间⾥不可⽤;我们希望这种情况在整个系统的运⾏中很少出现。
⼴播时间和平均故障间隔时间是由系统决定的,但是选举超时时间是我们⾃⼰选择的。Raft 的 RPCs 需要接收⽅将信息持久化的保存到稳定存储中去,所以⼴播时间⼤约是 0.5 毫秒到 20 毫秒,取决于存储的技术。因此,选举超时时间可能需要在 10 毫秒到 500 毫秒之间。⼤多数的服务器的平均故障间隔时间都在⼏个⽉甚⾄更长,很容易满⾜时间的需求。
Raft排序和kafka排序的对⽐
蛇板从提供服务的视⾓来看,基于Raft和kafka的排序服务是类似的,他们都是基于CFT(crash fault tolerant)模型的排序服务,并且都使⽤了主从节点的设置。但是Raft⽐kafka有以下优势:
kafka和zookeeper的设计不适⽤于⼤型⽹络。它们的设计是CFT模型,但局限于运⾏的⽐较紧密的主机上。也就是说,需要有⼀个组织专门运⾏kafka集。鉴于此,当有多个组织使⽤基于kafka排序服务的时候,其实没有实现去中⼼化,因为所有的节点连接的都是由⼀个组织单独控制的kafka集。如果使⽤Raft算法,每个组织可以贡献排序节点,共同组成排序服务,可以更好的去中⼼化。
Raft是原⽣⽀持的,⽽kafka需要经过复杂的步骤部署,并且需要单独学习成本。⽽且kafka和zookeeper的⽀持相关的issue要通过apache来处理,⽽不是Hyperledger Fabric。Raft的实现是包含在Fabric社区的,开发⽀持更加便利。
系统架构不同
kafka共识:
在kafka共识模式中,orderer与orderer之间不会互相直接建⽴连接,⽽是与kafka连接。这种共识模式中,依赖于外部的kafka集系统和zookeeper集系统。每个orderer会把⾃⼰的交易发送给kafka集,交易在kafka对应的topic中排序后,kafka把排序后的交易推送给orderer节点。Orderer节点收到交易后对交易打包,然后发给peer。
Raft共识:
在Raft共识模式中,orderer与orderer之间直接建⽴连接,不依赖外部系统。在orderer节点中,会创建Raft的协程来处理与其他orderer 的通信。

本文发布于:2024-09-22 17:30:45,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/2/109656.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:领导   选举   跟随者   服务器   节点   领导者   候选   时间
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议