《深入理解 Nacos 集群与 Raft 协议》系列五:为什么集群未过半,系统就不可用?从 Raft 的投票机制说起

《深入理解 Nacos 集群与 Raft 协议》系列

大家好,我是G探险者!

很多人部署 Nacos 集群时,会遇到这样一个问题:

我明明部署了 5 个节点,但只启动了 2 个,为什么系统完全无法使用?

这不是 Nacos 的 Bug,而是 Raft 共识算法的一个核心设计 ------ "过半存活原则"。

本篇我们将深入讲解:

  • 为什么需要超过一半节点存活?
  • 如果未过半,系统会发生什么?
  • 如何从理论上理解这个约束?

一、Raft 的"过半投票原则"

Raft 在以下两个地方都要求"过半节点确认"才能推进:

  1. 选主(Leader Election):候选人需要获得超过半数节点投票才能成为 Leader
  2. 日志提交(Log Commitment):Leader 的日志条目,必须被超过半数节点确认,才能算"已提交"

这两个约束,是整个 Raft 一致性协议的核心。

→ 所以,没有过半节点存活,就选不出 Leader,无法提交日志,系统即不可用。


二、举例说明:三种典型节点数量

节点数 最小存活数(过半)
3 2
5 3
8 5

假设你部署了 8 个节点,只启动了 4 个,那就无法满足"超过 8/2 = 4"这个条件 → 系统无法进行任何写操作,甚至部分读操作也会失败(因为没有 Leader)。


三、为什么非得"过半"?

这是为了防止脑裂和数据丢失。

我们来思考一个问题:

如果 5 个节点中,A、B 两个节点单独启动,不满足过半,但系统仍允许它们工作,那会发生什么?

  • A 成为了 Leader,写入一条日志(仅 A、B 有)
  • 突然 A、B 宕机,C、D、E 启动,C 成为新 Leader
  • C 重复写入了另一条日志(无 A、B 的写入)

→ 日志分叉!数据丢失!

为了避免这种情况,Raft 要求任何 Leader 的日志必须获得"过半副本确认",才能提交。

而一个节点想当选为 Leader,也必须能拿到过半选票。

所以,如果你活跃节点不满过半:

  • 不能选主
  • 原 Leader 无法继续领导(因心跳无响应)
  • 所有提交机制暂停

→ 系统进入保护性停顿状态,而非错误工作。


四、Nacos 集群部署的建议

✅ 正确部署姿势

  • 总节点数建议奇数(3、5、7、9),避免投票平票
  • 启动时应确保至少过半节点在线,否则系统不工作

⚠️ 错误部署陷阱

  • 部署 8 个节点,仅启动 4 个 → 失败
  • 以为"部分可用" → 实则"不一致风险" → Raft 拒绝启动

五、可用性 vs 一致性

Raft 在设计时就做出了选择:

牺牲"部分可用性",换取"数据强一致性"

也就是说:

  • 哪怕你能读取,但 Leader 不确定日志已同步 → 暂停处理
  • 系统保证数据一致,而不是"不管三七二十一先返回"

这也是 Nacos、etcd、Consul 等注册中心使用 Raft 的原因:

  • 配置信息必须强一致(否则灰度配置不生效)
  • 服务列表变更必须可靠(否则服务发现错乱)

六、如何判断当前集群是否满足"过半"?

查看 Nacos 控制台日志或访问 /nacos/v1/ns/operator/raft/cluster 接口:

json 复制代码
{
  "leader": "nacos-1",
  "raftPeers": [
    {"ip": "nacos-1", "state": "LEADER"},
    {"ip": "nacos-2", "state": "FOLLOWER"},
    {"ip": "nacos-3", "state": "FOLLOWER"},
    ...
  ]
}

如日志中出现:

text 复制代码
no leader is available now!

说明未能选主,系统已进入"挂起"状态。


七、总结

Raft 是为了保证数据一致性而牺牲了可用性的一种协议。

  • 所有操作都要过半节点参与确认
  • 未过半时,为防止脑裂,系统主动进入保护性不可用
  • 在 Nacos 中体现为:Leader 无法选举、写请求挂起、读请求可能失败
相关推荐
念何架构之路7 分钟前
go-grpc设计思想
开发语言·后端·golang
system_error_x37 分钟前
SpringBoot 集成 Thymeleaf 简洁入门
java·spring boot·后端
步行cgn2 小时前
Spring MVC 视图机制的核心接口与类
java·开发语言·后端·spring·mvc
码事漫谈3 小时前
AI 读你的提示词,其实很没耐心
后端
用户8356290780514 小时前
如何使用 Python 格式化 Excel 单元格中的长文本
后端·python
我命由我123454 小时前
Python 开发 - Python 的 pathlib
java·开发语言·后端·python·学习·java-ee·学习方法
IT_陈寒4 小时前
Java性能优化完全指南
前端·人工智能·后端
电子IT笔记4 小时前
对接群晖NAS,上传和删除踩坑记录
前端·后端
Mk598784 小时前
P4:把 Agent 的记忆搬进 Redis —— AgentScope-Java 工程化实战
后端
雨中飘荡的记忆4 小时前
Claude Code 入门必会:@、!、Slash Commands,一篇讲清楚
人工智能·后端