#15857·nacos

[BUG] 在Nacos集群全量重启 / 多节点同时重启场景下,会造成服务实例丢失

Author: tiantian-qiCreated Sep 16, 2026Updated Sep 17, 2026
Labelskind/question

Describe the bug Nacos服务端节点启动时,会从集群其他节点拉取数据。与此同时,客户端重连后会触发 redo 重新注册。

在集群全量重启 / 多节点同时重启场景下,节点之间会互相拉取快照数据,存在并发竞争问题,复现流程如下:

  1. A节点先接收客户端注册的一部分服务数据;
  2. B节点从A节点拉取到这部分数据;
  3. A节点继续收到客户端新注册的另一部分服务数据;
  4. A节点从B节点拉取到快照,这份快照不包含A后续新注册的服务;A节点拿本地数据和B拉取过来的快照做对比,误将本地刚新增注册的服务删除;
  5. A节点删除后,将这份删除后的状态同步到集群其他节点,引发集群同步删除。

最终现象:同一个客户端,部分service保留实例数据,另外部分service实例永久丢失。 该问题只能通过重启客户端,或者重启对应客户端的responsible node服务端才能恢复。

Desktop

  • Nacos version: 2.5.2
  • Deploy Mode: Cluster
  • Module: Naming

Expected behavior 集群节点在未完成snapshot数据拉取、初始化就绪之前,拒绝接收客户端 register / subscribe 请求,避免新注册实例被快照对比逻辑误删。

如果当前节点是责任节点,跳过对此类客户端的处理

Possible Solution 新增 request filter,增加节点就绪状态判断。 当节点未完成初始化时,拦截非cluster类请求,防止数据缺失。

在处理拉取到的snapshot时,对客户端类型进行判断,如果当前节点是责任节点,不进行处理。依靠集群同步保证数据一致

Additional context 该问题在压测场景能稳定复现。

删除服务的代码在com.alibaba.nacos.naming.consistency.ephemeral.distro.v2.DistroClientDataProcessor#upgradeClient

java
private void upgradeClient(Client client, ClientSyncData clientSyncData) {
        ......
        for (Service each : client.getAllPublishedService()) {
            if (!syncedService.contains(each)) {
                client.removeServiceInstance(each);
                NotifyCenter.publishEvent(
                        new ClientOperationEvent.ClientDeregisterServiceEvent(each, client.getClientId()));
            }
        }
       ......
    }

处理snapshot数据和处理数据同步复用的是同一套逻辑