《深入理解 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 小时前
消息队列5-RabbitMQ的高级特性和MQ的应用问题与解决方案-事务、消息分发的应用、幂等性保证、顺序性保证、消息积压的解决
分布式·消息队列·rabbitmq
稻草猫.1 小时前
Spring事务操作全解析
java·数据库·后端·spring
希望永不加班2 小时前
SpringBoot 整合 MongoDB
java·spring boot·后端·mongodb·spring
Lzh编程小栈2 小时前
数据结构与算法之队列深度解析:循环队列+C 语言硬核实现 + 面试考点全梳理
c语言·开发语言·汇编·数据结构·后端·算法·面试
妙蛙种子3112 小时前
【Java设计模式 | 创建者模式】工厂方法模式
java·后端·设计模式·工厂方法模式
Arva .3 小时前
RabbitMQ
网络·分布式·rabbitmq
DYuW5gBmH3 小时前
Kafka 成功消费消息的完整流程图
分布式·kafka·流程图
freejackman4 小时前
Java从0到1---基础篇
java·开发语言·后端·idea
无心水5 小时前
20、Spring陷阱:Feign AOP切面为何失效?配置优先级如何“劫持”你的设置?
java·开发语言·后端·python·spring·java.time·java时间处理
0xDevNull5 小时前
Java 21 新特性概览与实战教程
java·开发语言·后端