(etcd)raft算法的学习笔记 (一)

论文原文:https://ramcloud.atlassian.net/wiki/download/attachments/6586375/raft.pdf
中文翻译:https://github.com/maemual/raft-zh_cn/blob/master/raft-zh_cn.md
相关动画:http://thesecretlivesofdata.com/raft/

一、什么是一致性算法
 一致性算法比较通俗的解释就是,让一组机器能像一个整体一样操作下去,哪怕其中的一台机器宕机了,整个集群也能继续操作下去。


  • 复制状态机
     一致性算法是在复制状态机的基础上提出来的,复制状态机赋予了一组机器相同的状态副本,在机器组内即使有一台机器宕机了,集群也可以通过一些机器活下来,例如通过领导人选举和存储着相同的信息等。
     日志。复制状态机的基础是靠日志同步,由于每台状态机上都存储着相同顺序和内容的日志,所以在所有的状态机上都会出现相同的操作结果。类似于,在多个相同的内核操作系统上并且在网络状态配置等相同的情况下执行同一个脚本,出来的结果肯定是相同的。
     一致性算法的工作。保证所有状态机的日志是同步就是一致性算法的工作。在某台机器上,接收来自client的指令,并同步到了自己的日志中去,然后通过一致性算法确保其他机器都接收到这个相同的指令并按顺序执行下去。
     特性。安全性保证,能够保证在丢包、网络延迟、分区、冗余和乱序等错误都可以保证正确。可用性,只要大部分机器正常就可用。不依赖时序来保证一致性。一条指令发送给一个集群,集群中小部分比较慢的节点不会影响整体的性能

  • RAFT AND PAXOS
     由于PAXOS算法的复杂和难于理解,因此在该算法的基础上提出了易于理解和更可行的raft算法。

二、raft算法
 Raft 通过选举一个leader,然后给予他全部的管理复制日志的责任来实现一致性。leader从客户端接收日志条目,把日志条目复制到其他服务器上,并且当保证安全性的时候告诉其他的服务器应用日志条目到他们的状态机中。leader简化了对复制日志的管理。例如,leader可以决定新的日志条目需要放在日志中的什么位置而不需要和其他服务器商议,并且数据都从leader流向其他服务器。一个leader可以宕机,可以和其他服务器失去连接。当宕机或失去连接时,集群会选着一个新的leader。

  • 三个子问题
     领导选举。当leader宕机或失去连接时,集群会选举一个新的leader。
     日志复制。leader必须从客户端接收日志然后复制到集群中的其他节点,并且强制要求其他节点的日志保持和自己相同。
     安全性。包括选举安全、leader日志仅追加、日志匹配、leader具有日志完整性、状态机安全。
  • 名词解释
状态
服务器上持久保留的状态 currentTerm votedFor log[]
服务器最新的任期号(初始化为0,并不断递增) 候选人在当前任期获得的选票 日志条目list;每个日志条目包含给状态机的命令和当收到日志条目时的任期号
服务器上经常变更的状态 commitIndex lastApplied
已经被提交的日志条目最新的index值 日志条目被运用到状态机的最新index值
leader经常变更的状态 nextIndex[] matchIndex[]
对于每个服务器来说需要发送给他的下一个索引值 对于每个服务器来说已经复制给它的日志条目的最新索引值
追加日志RPC(由leader调用去复制日志条目,同时用于heartbeat)
请求参数 term leaderId prevLogIndex prevLogTerm entries[] leaderCommit
leader的任期号 leader的id,让follower能够找到leader 最新的日志条目前面一条的索引值 prevLogIndex的任期号 要存的日志条目(一次可多条放入数组中从而提高效率;当数组为空时表示heartbeat) leader提交的日志的索引值
response term success
当前的任期号,用于leader去更新自己 当follower匹配条目匹配到prevLogIndex和prevLogTerm时,返回true
接收者执行的行动
返回 false 如果term小于currentTerm(5.1 节)
返回 false 如果日志在 prevLogIndex 位置处的日志条目的任期号和 prevLogTerm 不匹配,返回 false(5.3 节)
删除日志条目 如果已经存在的日志条目和新的产生冲突(索引值相同但是任期号不同),删除这一条和之后所有的 (5.3 节)
追加新日志条目未出现在现有日志中
改索引值 如果 leaderCommit > commitIndex,令 commitIndex 等于 leaderCommit 和新日志条目索引值中较小的一个
请求投票RPC(由candidates发起去获得选票)(5.2 节)
请求参数 term candidateId lastLogIndex lastLogTerm
candidate的任期号 请求选票的候选人id 候选人最新日志条目的索引 候选人最新日志条目的任期号
response term voteGranted
当前的任期号,用于candidate去更新自己 candidate是否赢的该选票,1为是
接收者执行的行动
返回 false 如果term小于currentTerm(5.2 节)
返回 false 如果 votedFor 为空或者为 candidateId,并且候选人的日志至少和自己一样新,那么就投票给他(5.2 节,5.4 节)
服务器需遵守的规则
所有服务器 如果commitIndex > lastApplied,那么就 lastApplied 加一,并把log[lastApplied]应用到状态机中(5.3 节)
如果RPC请求中任期号T > currentTerm,那么就令 currentTerm 等于 T,并切换状态为follower状态(5.1 节)
followers(5.2 节) 响应来自candidates和leaders的请求
如果计时器达到选举超时时间,并且没有收到leader的追加日志(心跳检测)的RPC请求或者是收到请求投票的请求,那么就切换到follower状态
candidates(5.2 节) 一旦转变为candidate就开始选举的过程:1⃣️增加当前的任期号 2⃣️给自己投一票 3⃣️重置选举超时计时器4⃣️发送请求投票RPC给其他所有的服务器
变为leader:收到绝大部分的服务器的投票
变为follower:收到leader的追加日志的RPC
如果选举过程超时则开始新一轮的选举
leader(5.2 节) 一旦转变为leader:发送一个初始新的AppendEntries RPC(心跳检测)给每个服务器;在一定的空闲时间内重复发送这个空的AppendEntries RPC(心跳检测),防止follower以为超时了(5.2 节)
收到client的命令:追加条目在本地日志中,并且在条目被应用到状态机后再响应给client(5.3 节)
如果leader最新的日志index ≥ follower的nextIndex,那么发送从nextindex开始的所有日志条目: 1⃣️成功,更新相应follower的nextIndex和matchIndex 2⃣️如果因为日志不一致而导致了追加失败,则减少nextIndex并且重试
令commitIndex = N:存在一个值N且N> commitIndex(已经被提交的日志条目最新的index值), 同时大多数matchIndex[I]≥ N(对于每个服务器来说已经复制给它的日志条目的最新索引值) ,并且log[N].term == currentTerm(5.3 和 5.4 节)

你可能感兴趣的:(算法,k8s,etch)