《深入理解 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 无法选举、写请求挂起、读请求可能失败
相关推荐
不死的精灵1 小时前
【Java21】在spring boot中使用ScopedValue
java·spring boot·后端
M1A11 小时前
TCP/IP协议精解:IP协议——互联网世界的邮政编码系统
后端·网络协议·tcp/ip
逸风尊者2 小时前
开发易掌握的知识:GeoHash查找附近空闲车辆
java·后端
程序猿阿越3 小时前
Kafka源码(一)Controller选举与创建Topic
java·后端·源码
程序员爱钓鱼3 小时前
Go语言项目工程化 — 常见开发工具与 CI/CD 支持
开发语言·后端·golang·gin
Jiude3 小时前
MinIO 社区版被故意阉割,Web管理功能全面移除。我来试试国产RustFS
后端·docker·架构
仰望星空@脚踏实地3 小时前
Spring Boot Web 服务单元测试设计指南
spring boot·后端·单元测试
羊小猪~~3 小时前
数据库学习笔记(十七)--触发器的使用
数据库·人工智能·后端·sql·深度学习·mysql·考研
用户8324951417324 小时前
JAVA 版本多版本切换 - 傻瓜式操作工具
后端
estarlee4 小时前
随机昵称网名API接口教程:轻松获取百万创意昵称库
后端