raft算法是干嘛的?
集群部署时,存在多台服务器
当出现问题: 集群中,某个节点宕机、节点网络异常、延迟、数据丢失不一致……
Paxos算法
为首批吃螃蟹人,为此做出了解决方案,一致性的思想作为衍生基础,例如:决策、复制、成员身份变更,并获得图灵奖
缺点:过于复杂,理论理解难度过大
一个动画理解算法地址
http://harry.me/blog/2014/12/27/neat-algorithms-paxos/
相对的开源产品有
ZooKeeper、MySQLGroup Replication(解决方案)
集群中,各台服务器间信息传递方式
- 共享内存:会议模式、资源共建
- 消息传递(raft所采用):信道的传递、安全、一致、完整,暂不是重点,在内网部署方面不考虑此方面的损耗
高级语言解决方案通常通过信息传递来共享内存
raft算法 基于此思想,做了简洁化处理,理论知识易于理解
相对的开源产品有
etcd、RocketMQ
新特性
- Strong leader:在 Raft 中,日志条目(log entries)只从 leader 流向其他服务器。 这简化了复制日志的管理,使得 raft 更容易理解
- Leader 选举:Raft 使用随机计时器进行 leader 选举。 这只需在任何一致性算法都需要的心跳(heartbeats)上增加少量机制,同时能够简单快速地解决冲突
- 成员变更:Raft 使用了一种新的联合一致性方法,其中两个不同配置的大多数在过渡期间重叠。 这允许集群在配置更改期间继续正常运行
复制状态机
- 客户端->服务器->log->状态机器->客户端
假设这是一条完整的作业流程,在保证完整性、顺序性、一致性情况下,那么成功执行的次数与生成的结果次数是对等的,对此流程生成结果命名为状态机,那么在3个原则情况下,这群状态机是可靠健壮的。
复制状态机模式,将机器指令归档化,方便一致性、理论性,方便实际工程的实现
对复制机的特别要求:
- 一个请求与响应,不存在拜占庭,宁可宕机也要摒弃
- 故障率的要求,容许故障后现存机器数应当>=3,哲学和算法中的综合体
- 一条作业流程,不应当让集群中慢的机器所拖累,这和分布式的分机计算为相反
身份
- Leader(领导者):接受客户端请求,并向Follower同步请求日志,当日志同步到大多数节点上后告诉Follower提交日志。
- Follower(跟从者):接受并持久化Leader同步的日志,在Leader告之日志可以提交之后,提交日志。
- Candidate(候选人):Leader选举过程中的临时角色。
- Stopped(停机状态):没被放弃的节点
选举制度
选举行政法应当有一套相对公平的竞选法则,如
- 应当每个节点都有票拟权
- 少数决议小于多数决议
- 选举结果应当是全局可靠一致的
角色分为
Proposer(提议者)、Acceptor(决策者)、Learner(s)(最终决策学习者)
对应的阶段
准备阶段(Prepare)、同意阶段(Accept)、学习阶段(Learn)
领导者与候选者的关系
- Follower只响应其他服务器的请求。如果Follower超时没有收到Leader的消息,它会成为一个Candidate并且开始一次Leader选举
- 收到大多数服务器投票的Candidate会成为新的Leader,Leader在宕机之前会一直保持Leader的状态
任期
- Raft算法将时间分为一个个的任期(term),每一个term的开始都是Leader选举
- 如果Leader选举失败,该term就会因为没有Leader而结束
单位间的通讯方式
心跳
选举过程
应用过程中,摒弃同享内存概念,不外乎初始化过程中,集群中是有一瞬间资源共享的
注意点
- 整个过程依赖RPC
- 整个过程中,系统处于不可用状态
初始化
各节点开始时均为Follower身份,此身份决定了只能响应其它节点信息,不可主动发送。
竞选
最开始的状态
Follower身份的所有节点,随机分配了一个超时时间(此时间依赖心跳),用来等待leader节点的心跳
当有Follower节点超时时间到了后,没有收到leader的请求,自身将切换身份为Candidate,自身的任期属性提升一届,向其它所有节点发送竞选信息
发送竞选的条件
- 身份需为Follower
- 超时时间到期
- 没有收到竞选请求
- 竞选请求中,携带有任期属性,在本一届中没投过票
一些投票规定
- Follower、Candidate通讯后,任期属性将会一致
- 同一届选举,票只能投一次
- 根据任期属性值,判断是否是合法可靠的竞选人
- 在超时时间结束后,谁赢得的票数最多(>n/2),当选leader,否则继续竞选
- 网络中有些Follower可能由于网络状态原因反应缓慢或者崩溃,那么Leader将会无限次地尝试重复发送AppendEntries RPC消息到该Follower,直到成功为止
- 挂掉的节点Stopped在重启后依旧可被集群中所覆盖,可重启用
当选通知
当届leader选举出后,全局发送心跳,Candidate、Follower将不再参与竞选、投票,本轮事务结束
作业模式
- 数据请求->leader生成指令->Follower接收并响应leader->leader收到多数后,自我提交,通知Follower提交->响应数据请求
这是一条完整的用户请求作业流程
索引、任期、指令 3个重要属性,为日志指令成功复制的核心
用户请求
leader节点的请求,不会立刻向其它节点发送RPC请求,仍然依赖下次的心跳请求来通讯
步骤图解
步骤图解 raft图解
大彻大悟的演示
raft动画地址
官方(幻灯片模式)
http://www.kailing.pub/raft/index.html
https://github.com/klboke/raft-animation
交互式,更直观
https://raft.github.io/raftscope/index.html
https://github.com/ongardie/raftscope
我的另一篇文章
https://blog.csdn.net/qq_37485347/article/details/142171337?spm=1001.2014.3001.5502
官方论文
https://raft.github.io/raft.pdf