分布式一致性算法相关
raft协议是有什么用?干嘛的?里面的状态机是啥?
好问题!Raft 是现代分布式系统的“地基之一”,理解它非常重要。我给你一个架构师视角的通俗解释 + 深入细节:
1️⃣ Raft 协议是什么
一句话:
Raft 是一种 分布式一致性协议(Consensus Algorithm),主要用于在一组分布式节点中,选举一个Leader,并让所有节点在面对宕机、网络抖动时,仍能就一系列日志(指令)达成一致。
📌 应用场景:
- 分布式数据库(Etcd、TiKV、CockroachDB、MongoDB副本集底层、MySQL Group Replication等)
- 配置中心(Etcd、Consul)
- 分布式协调服务(ZooKeeper 后来也在研究用 Raft 取代 Zab)
2️⃣ 为什么需要 Raft
在分布式环境中:
-
节点会宕机、重启、网络分区。
-
我们需要一个强一致的状态,比如:
- 分布式锁(不能两个人都拿到同一把锁)
- 银行账户余额(不能出现双花)
- 配置中心(所有服务拿到同样配置)
Raft 就是用来在不可靠环境下达成共识,保证所有节点应用相同的状态更新顺序,从而保证系统状态强一致。
3️⃣ Raft 的核心概念
🔑角色
- Leader:唯一的写入入口,客户端所有修改请求先发给 Leader。
- Follower:被动节点,接收 Leader 的日志复制。
- Candidate:竞选 Leader 的节点。
🔑核心机制
-
Leader 选举:
- Follower 如果在超时时间内没收到 Leader 心跳,就变 Candidate。
- Candidate 拉票(RequestVote),多数票通过即成为 Leader。
-
日志复制(Log Replication):
- Leader 接受客户端请求,将其作为日志条目(Log Entry)追加到日志。
- Leader 将日志条目发送给 Follower,Follower写入日志后应答。
- 一旦日志在大多数节点上提交,Leader 将该日志“提交”,并应用到状态机。
-
安全性保证:
- 使用Term(任期号)确保最新的 Leader 一定包含最新的日志。
- 即使出现网络分区,只要超过半数节点还连通,系统就能继续工作。
4️⃣ 状态机(State Machine)是啥?
这里的“状态机”是一个抽象概念:
-
Raft 协议本身只保证日志在所有节点上一致。
-
状态机是“如何解释日志”的地方。
-
可以把它理解为:
- 日志是“操作指令序列”
- 状态机是“执行这些操作的业务逻辑”
例子:
日志:
1. 存入账户A 100元
2. 从账户A转给B 50元状态机:
初始:A=0, B=0
执行后:A=50, B=50
每个节点有:
- 一致的日志副本
- 相同的状态机实现
所以所有节点最终应用相同指令 → 状态保持一致。
5️⃣ 类比帮助理解
-
Raft 就像一个公司:
- Leader = CEO
- Follower = 员工
- Candidate = 想竞选 CEO 的人
-
客户(用户请求)必须找 CEO 下达任务。
-
CEO 发邮件(日志)给所有员工抄送。
-
员工收到后“签收”(写到日志),等半数以上人签收了,CEO 才宣布任务“正式生效”。
-
每个人都按同一顺序执行任务,所以结果一致。
6️⃣ 和 2PC / TCC 区别
对比项 | Raft | 2PC | TCC |
---|---|---|---|
目标 | 节点间一致性(复制协议) | 跨服务事务提交 | 业务级补偿事务 |
粒度 | 复制日志条目 | 单个分布式事务 | 一组业务操作 |
容错能力 | 可自动恢复Leader,强一致 | 协调者崩溃需人工介入 | 可用性高,但最终一致 |
应用 | 分布式DB存储、配置中心 | 跨库事务 | 电商/支付业务逻辑 |
Raft 不是用来做分布式事务协议的,而是数据库或服务底层共识协议。如果底层存储已经是 Raft 强一致的,那么上层就不一定需要 2PC 了。
7️⃣ 总结一句话
Raft 是一种共识算法,用多数投票 + 日志复制来保证所有节点日志和状态机的一致性。
状态机是指“执行日志操作的确定性程序”,用它保证每个节点最终状态一致。
安全性保证:
使用Term(任期号)确保最新的 Leader 一定包含最新的日志。
即使出现网络分区,只要超过半数节点还连通,系统就能继续工作。
这里是啥意思?解释一下
好,这里说的安全性保证是 Raft 的核心设计亮点之一。我帮你详细拆开这两句话,结合网络分区的场景来解释。
🔑 1. 什么是 Term(任期号)
- Raft 把时间分成一个个逻辑“任期(Term)”,可以理解为“第几届 Leader 的任期”。
- 每次开始 Leader 选举时,节点会把自己的 term 增加 1。
- 所有日志条目也带有 term 信息。
好处:
- 任期号可以让所有节点知道“谁更新”。
- 如果一个节点看到的请求或 Leader term 比自己小,就会拒绝。
- 确保不会出现“旧 Leader”还在乱发命令的情况。
🔑 2. 为什么“最新 Leader 一定包含最新日志”
Raft 的选举规则:
- 选举时,Candidate 必须获得多数节点的投票。
- 节点投票时,会检查 Candidate 的日志是不是至少跟自己一样新,否则拒绝投票。
🔗 这意味着:
- 能赢得多数票的 Candidate 一定拥有系统中最新的日志。
- 这样就避免了“新 Leader 丢掉了一些已经提交的日志”的问题。
🔑 3. 网络分区下还能继续工作
假设有 5 个节点:
A, B, C, D, E
发生网络分区:
- 集群被分成了 3 个节点(A, B, C) 和 2 个节点(D, E)。
- A、B、C 还能互通,D、E 只能互通。
Raft 的多数票是 3(5/2 + 1):
- 分区中有 3 个节点的那一半能选出新的 Leader。
- 那个 Leader 可以继续对外提供服务,继续接收日志。
- 另一半(2 个节点)因为票数不够,不能选 Leader,也不会乱写数据。
💡 这就是 Raft 的“安全优先”:
只要多数节点连通,系统就能继续一致地运行;分区小于半数的节点变成“只读”Follower,不会造成脑裂。
🔑 4. 举个场景
-
5 节点集群,Leader 是 A。
-
网络出问题:
- A 跟 B、C 断了连接,只能跟 D、E 互通。
- A 所在分区是 3 节点,B、C 分区是 2 节点。
-
A 继续当 Leader,服务正常。
-
如果反过来:
- A 跟 B、C 连着,D、E 单独一组。
- B、C 票数够,可以选出新 Leader,继续服务;D、E 因为票数不够,无法选 Leader。
⚠️ Raft 确保不会有两个 Leader 同时提交冲突日志,因为:
- 同一任期只会有一个 Leader。
- 新 Leader 必须包含旧 Leader 的已提交日志。
🔑 总结
- Term = Raft 的“逻辑时钟”,保证每次选出的 Leader 是最新的,不会回退日志。
- 多数票机制 = 保证在网络分区时,只有多数节点的那一边能正常工作,防止脑裂和数据不一致。
- 安全性 = 不会丢已提交日志,不会出现两个 Leader 提交冲突日志。