概念:
分布式⼀致性算法:raft会先选举出leader,leader完全负责replicatedlog的管理。leader负责接受所有客户端更新请求,然后复制到follower节点,并在“安全”的时候执⾏这些请求。如果leader 故障,followes会重新选举出新的leader
三种状态:
⼀个节点任⼀时刻处于三者之⼀
leader:处理所有的客户端请求(如果客户端将请求发给了Follower,Follower将请求重定 向给
Leader)
follower:不会发送任何请求,只会简单地响应来⾃Leader或Candidate的请求
candidate:⽤于选举产⽣新的leader(候选⼈)
term:任期,leader产⽣到重新选举为⼀任期,每个节点都维持着当前的任期号
term是递增的,存储在log⽇志的entry中,代表当前entry是在哪⼀个term时期写⼊ 每个任期只能有⼀个leader或者没有(选举失败)
每次rpc通信时传递该任期号,如果RPC收到任期号⼤于本地的、切换为follower,⼩于本地 任期号则返回错误信息
两个RPC通信:
RequestVote RPC:负责选举,包含参数lastIndex,lastTerm AppendEntries RPC:负责数据的交
互。
⽇志序列:每⼀个节点上维持着⼀份持久化Log,通过⼀致性协议算法,保证每⼀个节点中的Log 保持⼀致,并且顺序存放,这样客户端就可以在每⼀个节点中读取到相同的数据
状态机:⽇志序列同步到多数节点时,leader将该⽇志提交到状态机,并在下⼀次⼼跳通知所有节点提交状态机(携带最后提交的lastIndex)
何时触发选举:
集群初始化时,都是follower,随机超时,变成candidate,发起选举
如果follower在election timeout内没有收到来⾃leader的⼼跳,则主动触发选举
选举过程:
发出选举的节点⻆度
-
增加节点本地的term,切换到candidate状态
-
投⾃⼰⼀票其他节点投票逻辑:每个节点同⼀任期最多只能投⼀票,候选⼈知道的信息不能⽐⾃⼰少(通过副 本⽇志和 安全机制保障),先来先得
-
并⾏给其他节点发送
RequestVote RPCs
(选举请求)、包含term参数
-
等待回复
-
收到majority(⼤多数)的投票,赢得选举,切换到leader状态,⽴刻给所有节点发⼼跳消息
-
被告知别⼈当选,切换到follower状态。(原来的leader对⽐term,⽐⾃⼰的⼤,转换到
follower状态)
-
⼀段时间没收到majority和leader的⼼跳通知,则保持candidate、重新发出选举
⽇志序列同步:
⽇志需要存储在磁盘持久化,崩溃可以从⽇志恢复
-
客户端发送命令给Leader
-
-
Leader发送AppendEntriesRPC请求给所有的follower
携带了prevLogIndex,prevLogTerm ,follower收到后,进⾏⽇志序列匹配
匹配上则追加到⾃⼰的⽇志序列
匹配不上则拒绝请求,leader将⽇志index调⼩,重新同步直⾄匹配上,follower将leader的⽇志序列覆盖到本地
⼀旦新的⽇志序列条⽬变成majority的了,将⽇志序列应⽤到状态机中
Leader在状态机⾥提交⾃⼰⽇志序列条⽬,然后返回结果给客户端
Leader下次发送AppendEntriesRPC时,告知follower已经提交的⽇志序列条⽬信息(lastIndex)
follower收到RPC后,提交到⾃⼰的状态机⾥
提交状态机时,如果term为上⼀任期,必须与当前任期数据⼀起提交,否则可能出现覆盖已提交状态机的⽇志
新选举出的leader⼀定拥有所有已提交状态机的⽇志条⽬
leader在当⽇志序列条⽬已经复制到⼤多数follower机器上时,才会提交⽇志条⽬。
⽽选出的leader的logIndex必须⼤于等于⼤多数节点,因此leader肯定有最新的⽇志
安全原则:
选举安全原则:对于⼀个给定的任期号,最多只会有⼀个领导⼈被选举出来
状态机安全原则:如果⼀个leader已经在给定的索引值位置的⽇志条⽬应⽤到状态机中,那么其他任何的服务器在这个索引位置不会提交⼀个不同的⽇志
领导⼈完全原则:如果某个⽇志条⽬在某个任期号中已经被提交,那么这个条⽬必然出现在更⼤任 期号的所有领导⼈中
领导⼈只附加原则:领导⼈绝对不会删除或者覆盖⾃⼰的⽇志,只会增加
⽇志匹配原则:如果两个⽇志在相同的索引位置的⽇志条⽬的任期号相同,那么我们就认为这个⽇ 志从头到这个索引位置之间全部完全相同