Nacos 一致性协议

注册中心的实例数据分布在多个节点上,节点之间如何保证一致,是理解 Nacos 行为的关键。Nacos 按实例类型自动选择协议:临时实例走 AP,持久实例走 CP。

两种实例,两套协议

AP 与 CP 两套协议 第 2 章提过 ephemeral 参数,它决定的不只是"要不要落库",更决定了用哪套一致性协议:

实例类型默认值一致性协议典型场景
临时实例ephemeral=trueAP类 Distro 协议(节点间异步复制)微服务常规注册
持久实例ephemeral=falseCP基于 Raft 的副本协议(2.x 自研实现 + JRaft)DNS、Service Mesh、需长期稳定的服务

临时实例:AP 的取舍

临时实例量大、生命周期短,Nacos 为它实现了无单点的 AP 方案,要点是:

  • 每个节点都能独立读写,没有强主节点,挂一个不影响整体
  • 实例数据在节点间异步复制,写操作先本地生效再同步给别人
  • 牺牲"强一致"换取"高可用":某个节点可能短暂读到另一节点还没同步到的数据

对注册中心来说这通常可以接受:实例列表短暂旧一点,远好过"写不进去导致服务起不来"。

持久实例:CP 的取舍

持久实例需要可靠保存、多副本一致,Nacos 让这类数据走基于 Raft 的副本协议:

  • 集群先选举出 leader,写请求由 leader 处理
  • 多数派节点确认后才算提交成功(多数派写)
  • 少数派节点或 leader 故障时,从副本中重新选主,保证已提交数据不丢

代价是写入链路更重,且选主期间可能短暂不可写——所以持久实例适合数量不多但必须可靠的服务。

AP 与 CP 对比

维度AP(临时实例)CP(持久实例)
一致性最终一致,允许短暂读到旧数据强一致,多数派确认才成功
可用性节点故障时读写基本不受影响选举期间短暂不可写,已提交数据可读
数据落库不落库,靠心跳维护持久化存储
适合规模成千上万实例的动态微服务数量少、要求稳定的场景

为什么注册中心常用 AP

注册信息本质是"短暂状态":实例活着才有意义,心跳停了自然会被摘除。调用方偶尔拿到一个刚下线的实例,最多是本次调用失败重试一次;但如果为了强一致让注册写入经常失败或阻塞,整个微服务集群都无法启动。所以日常微服务都用默认的临时实例(AP)。

配置管理则相反:配置内容必须人人一致,错的配置会影响所有节点,因此配置数据依赖持久化存储(单机 Derby 或集群 MySQL)保证一致,详见第 11 章。

Nacos 如何自动选择

不需要手动指定协议:注册时带不带 ephemeral 参数即可。OpenAPI 注册时显式传 ephemeral 字段:

# 持久实例:ephemeral=false 走 CP
curl -X POST 'http://localhost:8848/nacos/v1/ns/instance' \
  -d 'serviceName=gateway-dns&ip=192.168.1.10&port=8080&ephemeral=false'
# 输出:ok

不传该参数时默认 ephemeral=true,即临时实例走 AP。

故障场景行为

  • AP 集群挂一个节点:剩余节点照常注册、发现,数据随后异步补齐
  • CP(Raft 副本)leader 故障:触发重新选主,选举窗口内写请求短暂失败或等待,已提交数据仍可读;多数派节点存活才能选出新 leader

小结

一句话记牢:临时实例 AP 保可用、持久实例 CP 保一致,Nacos 用 ephemeral 字段自动切换。日常微服务用默认的 AP 临时实例即可;需要"注册信息必须可靠保存"的场景(如 DNS、Service Mesh 的数据面)才考虑持久实例。

笔记加载中…