Raft
raft 会进入脑裂状态吗?描述下场景,怎么解决?
不会。raft通过选举安全性解决了这个问题:
- 一个任期内,follower 只会投票一次票,且先来先得;
- Candidate 存储的日志至少要和 follower 一样新;
- 只有获得超过半数投票才有机会成为 leader;
讲一下 raft 的 leader 选举流程
Leader 在任期内会周期性向其他 follower 节点发送心跳来维持地位。follower 如果发现心跳超时,就认为 leader 节点宕机或不存在。随机等待一定时间后,follower 会发起选举,变成 candidate,然后去竞选 leader。选举结果有三种情况:
- 获取超过半数投票,赢得选举:
- 当 Candidate 获得超过半数的投票时,化为 leader。会向其他节点发送请求,确认自己的 leader 地位,从而阻止新一轮的选举
- 投票原则:当多个 Candidate 竞选 Leader 时:
- 一个任期内,follower 只会投票一次票,且投票先来显得;
- Candidate 存储的日志至少要和 follower 一样新(安全性准则),否则拒绝投票;
- 投票未超过半数,选举失败:
- 当 Candidate 没有获得超过半数的投票时,说明多个 Candidate 竞争投票导致过于分散,或者出现了丢包现象。此时,认为当期任期选举失败,任期 TermId+1,然后发起新一轮选举;
- 收到其他 Leader 通信请求:
- 如果 Candidate 收到其他声称自己是 Leader 的请求的时候,通过任期 TermId 来判断是否处理;
- 如果请求的任期 TermId 不小于 Candidate 当前任期 TermId,那么 Candidate 会承认该 Leader 的合法地位并转化为 Follower;
- 否则,拒绝这次请求,并继续保持 Candidate;
如果主仲裁一致写入但是没有回复成功的时候挂了怎么办
加消息序列号,如果已经写入直接返回成功
时钟不准确问题
raft不依赖墙上时钟,而是使用逻辑日志解决
有多个 candidate 发起选举怎么解决?
选举时间设置为随机的150ms到300ms之间,为了尽量避免产生多个candidate的情况。
如果多个follower同时变为candidate,那么有可能出现票数<n/2+1的情况,导致选举失败,开始下一轮选举。
什么是幽灵复现问题?描述一下?raft会出现这些问题吗?raft如何解决?
第一种场景(raft不会出现,因为旧主的任期号和日志小于新主,不会被通过)
- 第一轮中A被选为Leader,写下了1-10号日志,其中1-5号日志形成了多数派,并且已给客户端应答,而对于6-10号日志,客户端超时未能得到应答。
- 第二轮,A宕机,B被选为Leader,由于B和C的最大的logID都是5,因此B不会去重确认6-10号日志,而是从6开始写新的日志,此时如果客户端来查询的话,是查询不到6-10号日志内容的,此后第二轮又写入了6-20号日志,但是只有6号和20号日志在多数派上持久化成功。
- 第三轮,A又被选为Leader,从多数派中可以得到最大logID为20,因此要将7-20号日志执行重确认,其中就包括了A上的7-10号日志,之后客户端再来查询的话,会发现上次查询不到的7-10号日志又像幽灵一样重新出现了。
第二种场景
(1)Round 1,A节点为leader,Log entry 5,6内容还没有commit,A节点发生宕机。这个时候client 是查询不到 Log entry 5,6里面的内容
(2)Round 2,B成为Leader, B中Log entry 3, 4内容复制到C中, 并且在B为主的期间内没有写入任何内容。
(3)Round 3,A 恢复并且B、C发生重启,A又重新选为leader, 那么Log entry 5, 6内容又被复制到B和C中,这个时候client再查询就查询到Log entry 5, 6 里面的内容了。
对于之前Term的未Committed数据,修复到多数节点,且在新的Term下至少有一条新的Log Entry被复制或修复到多数节点之后,才能认为之前未Committed的Log Entry转为Committed。
选举超时的设置一般多久,为什么这么设置?
随机的150ms到300ms
优化raft读请求
假如我在当前 Leader 上读时,其它节点已经选出了一个新的 Leader,并且写入了新的内容,而当前旧 Leader 暂时没有感知到这个变化,而是正常执行了读操作,显然读取到的也不是最新的内容。
- breatheart方案