引言:为什么需要共识算法?

在分布式系统中,节点可能崩溃、网络可能分区、消息可能丢失。面对这些故障,如何让多个节点就某个值达成一致?这正是共识(Consensus)算法要解决的核心问题。从 Paxos 到 Raft,从 ZAB 到 Gossip,共识算法是分布式系统的基石。

Raft 算法由 Diego Ongaro 和 John Ousterhout 在 2014 年的论文《In Search of an Understandable Consensus Algorithm》中提出。相比 Paxos 的"难以理解",Raft 通过"分离"策略——将共识问题拆分为 Leader 选举、日志复制和安全性三个相对独立的子问题——大幅降低了理解和实现的门槛。如今,Raft 已被广泛应用于 etcd、TiKV、Consul、CockroachDB 等生产级系统中。

本文将从 Raft 的核心原理出发,逐步深入到 Rust 工程实现,最终构建一个支持线性一致性的分布式键值存储。

一、Raft 基础:Term 与角色状态机

1.1 任期机制(Term)

Raft 将时间划分为一个个连续的任期(Term),每个 Term 是一个单调递增的整数。Term 是逻辑时钟,用于标识数据的"新旧"——拥有更高 Term 的节点始终被视为更权威。每个节点维护 current_term,并在 RPC 通信中携带 Term 信息:

当节点收到 RPC 请求或响应时:
  if args.term > current_term:
      current_term = args.term
      role = Follower       // 立即降级为 Follower
      voted_for = None      // 清除投票记录

13种角色与状态

Raft 中每个节点在任意时刻只扮演三种角色之一:

  • Leader:唯一处理客户端请求的节点,负责日志复制给所有 Follower
  • Followers:被动接收 Leader 的心跳和日志,超时则转为 Candidate
  • Candidate:发起投票试图成为 Leader,获得多数票后晋升为 Leader

状态转移图核心规则:

Follower → Candidate: election_timeout 超时(通常 150-300ms 随机化)
Candidate → Leader: 获得同一 Term 中多数节点(N/2 1)的投票
Leader → Follower: 发现更高 Term 的请求或响应
Candidate → Follower: 发现更高 Term 或合法 Leader 的心跳

二、Leader 选举:多数派投票机制

2.1 选举触发与投票流程

当 Follower 在 election_timeout 内未收到 Leader 心跳时,它自增 Term、转为 Candidate、先投自己一票,然后向所有其他节点发送 RequestVote RPC。

每个节点在每个 Term 内最多投给一个 Candidate(先到先得原则),投票请求中包含 Candidate 的最后日志索引和 Term,以确保"日志至少一样新"的节点才能当选:

class RequestVote:
    term: u64           // Candidate 的 Term
    candidate_id: u64   // Candidate 的节点 ID
    last_log_index: u64 // Candidate 最后日志的索引
    last_log_term: u64  // Candidate 最后日志的 Term

投票拒绝条件(满足任一即拒绝):
  1. args.term < current_term
  2. voted_for 不为空且不等于 candidate_id
  3. Candidate 的日志不如本节点更新(比较最后日志的 Term;Term 相同则比较 index)

2.2 选举超时随机化

多个 Follower 同时超时会引发"split vote"(平票),导致多次选举失败。Raft 通过让每个节点在 [150ms, 300ms] 范围内随机选取超时时间,大幅降低了并发选举冲突的概率。实践中,3 节点集群的首轮选举成功率

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部