《深入理解 Nacos 集群与 Raft 协议》系列
大家好,我是G探险者!
在使用 Nacos 作为注册中心进行集群部署时,很多人会遇到一个问题:明明配置了 8 个节点,启动了其中 4 个,却发现集群无法正常工作,报错"集群未过半,无法选主"。那么,为什么必须过半节点才能启动集群? 这背后其实隐藏着一个关键的共识协议 ------ Raft。
一、Nacos 为什么要使用 Raft?
Nacos 为了实现注册中心的"多节点一致性",引入了分布式一致性协议 Raft。
注册中心的核心是:所有节点看到的数据必须一致。 比如:服务 A 注册到了注册中心,不能有节点 A 看到,有节点 B 看不到,否则会引发服务发现混乱。
传统方式可以通过数据库实现一致性,但在高可用、高性能的分布式场景下,Nacos 选用了 Raft:
- 强一致性:数据写入必须经过多数节点确认;
- 自动容错:部分节点宕机不影响整体运行;
- 可控性强:相较于 Paxos 更易于实现与理解。
二、Raft 中的"多数派原则"
Raft 协议要求所有提交的写入,必须被集群中超过半数的节点确认,才算成功。
假设有 N
个节点,只要有 ⌊N/2⌋ + 1
个节点存活且响应正常,就可以进行以下操作:
- 正确地进行选主(Leader Election)
- 正确地接收客户端写入请求
- 正确地进行数据同步和日志复制
比如:
总节点数 | 需要存活节点(过半) |
---|---|
3 | 2 |
5 | 3 |
8 | 5 |
如果只启动了 4 个节点,仍然不足 5 个,就不能完成写入确认,也无法选出 Leader,集群判定为不可用。
三、集群无法过半会出现什么现象?
- 控制台无法正常展示注册服务
- 注册请求(如 POST /instance)会失败
- 日志中频繁报错:
leader is null
,No leader node found
,RAFT not available
- 甚至连
nacos-server
本身都不完整启动
原因是:没有 Leader,Nacos 就无法对外提供服务。
四、举个例子帮助理解
假设你部署了一个包含 A、B、C、D、E 共 5 个节点的 Nacos 集群:
- 正常情况下,只要活着其中的 3 个节点(比如 A、B、C),就可以继续服务。
- 但如果宕机了 3 个节点,只剩下 A、B,那么集群判定为"未过半",不能选主,也就无法继续写入。
这就是 Raft 的"多数派写入确认"的核心逻辑。
五、为什么不是"能活几个就用几个"?
很多人疑惑:"我有 8 个节点,起了 4 个不也不少了吗?为啥还不行?"
这是因为:
- 如果允许 4/8 成立,两个不同分区都能对外服务,会出现脑裂
- 脑裂会导致不同节点状态不一致,注册中心的数据就不再可靠
- Raft 为了防止脑裂,强制所有写入必须获得大多数节点的认可,哪怕代价是集群"降级不可用"
这也是 Raft 与一些"弱一致性"系统(如 Redis Sentinel)最大的不同:
Raft 牺牲了部分可用性(AP)来换取强一致性(CP)
六、Nacos 的"集群未过半"解决方案
你可以从两个方面入手:
✅ 方案一:至少启动过半节点
- 如果你配置了 8 个节点,至少要保证启动并联通其中的 5 个,否则集群就无法工作
- 推荐部署奇数节点:3、5、7,便于容错
✅ 方案二:不要配置太多节点
- 实际上 Nacos 3~5 个节点就足够满足高可用需求
- 节点越多,不仅选主更慢,还更容易出现"无法过半"的情况
总结
Nacos 集群部署时的"必须过半节点存活"要求,源于它底层使用的 Raft 协议。
Raft 强制多数派达成共识才能提交数据,是为了:
- 保证集群状态的一致性(避免脑裂)
- 保证注册数据的可靠传播与持久化
- 保证集群内部的正确选主
下一篇我们将深入讲解:
💡 Raft 为什么要选主?选主的条件、过程与常见误区
敬请期待第 2 篇!