订阅更新

Raft 是怎么选主和保证日志一致的?

面试问 360 约 2 分钟读完

随机一题
本文目录
  1. 面试怎么回答
  2. 三种角色和任期
  3. 选主
  4. 日志复制
  5. 为什么是过半

面试怎么回答

Raft 分 Leader、Follower、Candidate 三种角色,按任期划分时间。Follower 超时收不到心跳就升任期发起选举,每个节点每个任期只投一票、且只投给日志不比自己旧的候选人,拿到过半票成为 Leader。写入只走 Leader,日志复制到过半节点即算提交,再应用到状态机;Follower 日志不一致时由 Leader 回退并覆盖。过半保证了任意两次多数派有交集,新 Leader 一定包含所有已提交日志,所以 2N+1 个节点能容忍 N 个故障。

先把这段讲顺;面试官追问时,再展开下面的原理和细节。

详细讲解

Kafka 的 KRaft、etcd、TiKV 都基于 Raft。面试官会问:Raft 怎么选出 Leader?怎么保证各节点日志一致?为什么要过半?

三种角色和任期

节点分为 Leader、Follower、Candidate。时间被划分为一个个任期(term),每个任期最多一个 Leader。

选主

  1. Follower 在一段随机的超时时间内没收到 Leader 心跳,就把任期加一,变成 Candidate,向其他节点请求投票;
  2. 每个节点在一个任期内只投一票,并且只投给日志不比自己旧的候选人;
  3. 拿到过半票的候选人成为 Leader,开始发送心跳。

随机超时是为了减少多个节点同时发起选举、票数被瓜分的情况。

日志复制

客户端的写请求只发给 Leader:

  1. Leader 把命令追加到自己的日志,再并行发给各 Follower;
  2. 过半节点(包括 Leader 自己)写入成功后,这条日志被认为已提交(committed),Leader 应用到状态机并返回客户端;
  3. Follower 通过后续的心跳得知提交位置,再应用到自己的状态机。

如果某个 Follower 的日志和 Leader 不一致,Leader 会找到两者最后一致的位置,用自己的日志覆盖 Follower 后面的部分。

为什么是过半

任意两个「过半」集合一定有交集。已提交的日志至少存在于过半节点上;新 Leader 也必须拿到过半选票,而投票规则要求候选人的日志不比投票者旧,所以新 Leader 一定包含所有已提交的日志,提交过的数据不会丢。

这也意味着 2N+1 个节点最多容忍 N 个故障,所以集群通常是 3 个或 5 个节点。