ETCD介绍 (二)
Raft协议
- Raft is a consensus algorithm that is designed to be easy to understand(强一致性算法)
Raft 角色
- Leader(领袖):领袖由群众投票选举得出,每次选举,只能选出一名领袖;负责Client交互和log复制,同一时刻系统中最多存在1个
- Candidate(候选人):当没有领袖时,某些群众可以成为候选人,然后去竞争领袖的位置;由Follower向Leader转换的中间状态
- Follower(群众):群众,被动响应请求RPC,从不主动发起请求RPC
选举过程中的概念:
- Leader Election(领导人选举):简称选举,就是从候选人中选出领袖;
- Term(任期):它其实是个单独递增的连续数字,每进行一次选举值就会加1;
- Election Timeout(选举超时):就是一个超时时间,当成一个闹钟或定时器吧,当在这个超时时间内,未收到领袖的心跳时,闹钟会响提醒群众重新进行选举。
- Vote:投票,当follower收到投票请求时,需要回应投票
角色转换
- 群众 -> 候选人:当开始选举,或者“选举超时”(闹钟响)时
- 候选人 -> 候选人:当“选举超时”(情况比较特殊,当出现多个候选人并且选票相同)
- 候选人 -> 领袖:获取大多数投票时
- 候选人 -> 群众:发现其它节点已经成为领袖
- 领袖 -> 群众:发现自己的任期ID比其它节点分任期ID小时,会自动放弃领袖位置
图解角色转换
选举
Heartbeats and Timeouts
- 所有的Server均以Follower角色启动,并启动选举定时器(随机时间150ms-300ms)
- Follower被动从Leader或者Candidate接收RPC,不主动发起RPC
- Leader必须广播Heartbeat,Follower收到会重置自身的选举定时器
- 如果Follower选举定时器超时(则认为Leader已经crash),立即发起选举成为候选人
选举投票规则
- 每个群众手中只有一票。
- 只有候选者才能给自己投票。
- 当群众收到别人拉票,手中有票就立即投票
- 当有多个候选者时,票数多的候选者当选领导
选举角色定义
理想情况下选举过程(Leader election )
- 集群服务启动,定时器开始运行
- 群众发现自身的选举定时器超时,自增currentTerm +1,由Follower转换为Candidate,设置votedFor为自身(给自己投票), 并行发起RequestVote RPC
- 其他群众收到拉票,回复投票,并自增currentTerm +1,然后重置自身的选举计时器
- 候选人获得超过半数Server (N+1)/2的投票,转换为Leader
- Leader开始发送广播Heartbeat探测的RPC
- 群众收到心跳探测,重置自身选举定时器,并回复Leader自己活着。
Leader election 异常情况下选举过程
-
情况一:leader挂掉 (群众收不到健康探测 -> 选举超时 -> 开始选举)
-
情况二:出现多个候选者(几率很小)
脑裂情况
- 当网络问题导致脑裂,出现双Leader情况时,即出现了两个独立的网络。
- 没有leader的区域中的群众会自发开始新一轮的选举leader
- 出现两个leader,当用户向集群提交更新时,因Raft规则,需要在集群中大于(n+1)/2节点落盘后,才会更新成功,所以节点数少的那块区域的节点将不会更新数据
- 当网络恢复之后,旧的Leader发现集群中的新Leader的Term比自己大,则自动降级为Follower,并从新Leader处同步数据达成集群数据一致
节点最优选择
「用户的读请求每个节点都可以处理,写请求会转发有leader节点来处理」
- 集群节点并不是越多越好,要根据实际使用场景选择,根据Raft算法原理,节点数量越多,会降低集群写数据性能(而读性能变强),因为每一次的写操作都需要集群中 >=(N+1)/2 个节点罗盘后,leader才会修改内部状态机,最后返回用户
- 一般选择数量3、5、7、9个节点,不建议选择偶数个节点,原因如下
- 不可用风险高,选举过程容易出现相同票数,从而触发下一轮选举
- 脑裂情况下会导致集群不可用,想象一下当集群节点被对半分割开了,但Raft算法原理中对写数据需要 >=(N+1)/2 个节点同意才能成功写入,从而会导致写失败,集群无法正常工作
当然,还有其他各种异常情况,具体可以参考《云原生分布式存储基石-etcd深入解析》书中的“1.4.3 异常情况”这一章,里面讲述的比较清楚。