[BUG] 在Nacos集群全量重启 / 多节点同时重启场景下,会造成服务实例丢失
Author: tiantian-qiCreated Sep 16, 2026Updated Sep 17, 2026
Labelskind/question
Describe the bug Nacos服务端节点启动时,会从集群其他节点拉取数据。与此同时,客户端重连后会触发 redo 重新注册。
在集群全量重启 / 多节点同时重启场景下,节点之间会互相拉取快照数据,存在并发竞争问题,复现流程如下:
- A节点先接收客户端注册的一部分服务数据;
- B节点从A节点拉取到这部分数据;
- A节点继续收到客户端新注册的另一部分服务数据;
- A节点从B节点拉取到快照,这份快照不包含A后续新注册的服务;A节点拿本地数据和B拉取过来的快照做对比,误将本地刚新增注册的服务删除;
- 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
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数据和处理数据同步复用的是同一套逻辑
Source: alibaba/nacos