在 Redis 集群进行缩容操作时,最令人头疼的报错莫过于:ERR Target node is not empty. All slots must be covered by other nodes。这句错误信息直白地揭示了问题所在——目标节点仍然持有部分槽位(slot),导致集群拒绝将其移除。Redis 集群采用严格的元数据一致性机制:只要该节点上执行 CLUSTER SLOTS 返回非空结果,del-node 命令就会直接失败,毫无商量余地。

ERR Target node is not empty. All slots must be covered by other nodes 的含义
这条报错是 redis-cli --cluster del-node 执行时最常遇到的阻碍。通俗来说,就是目标节点仍然占据着至少一个槽位,Redis 集群因此拒绝将其移除。集群的元数据强一致性机制决定了:只要 CLUSTER SLOTS 在该节点上返回非空结果,del-node 就会直接失败,没有任何变通余地。
为什么 reshard 迁移完成后,旧节点仍可能显示有槽位
发出迁移命令并不等于迁移完成——这个坑很多人踩过,常见卡点包括:
- 在
redis-cli --cluster reshard交互式流程中,错误地填写了host:port而非 40 位node id,导致目标节点状态卡在IMPORTING,源节点卡在MIGRATING,槽位实际未完成归属变更 - 迁移过程中客户端持续写入,且未正确处理
ASK或MOVED重定向,造成部分 key 仍滞留在旧节点 - 执行完 reshard 后立即查询
CLUSTER SLOTS,未等待集群配置更新传播完成(通常需要 1–2 秒的延迟)
验证是否真正清空的方法很简单:连接旧节点执行 CLUSTER SLOTS,必须返回 [];再连接任意其他节点执行 CLUSTER NODES,确认旧节点状态为 fail? 或已彻底消失。
del-node 成功后,为什么旧节点进程仍在运行
del-node 只是让集群“忘记”这个节点,并不会关闭进程、删除数据或清理磁盘。你需要手动执行以下操作:
- 登录旧节点所在机器,执行
redis-cli -p(或shutdown kill对应进程) - 如果使用 Docker 部署,需执行
docker stop容器,不能仅删除节点元数据 - 客户端连接池需要主动刷新:旧连接仍可能指向已下线节点 IP,导致请求超时或写入数据丢失,必须重新加载或重启应用
跳过这一步,等于留下了一个“幽灵节点”——表面下线,实际仍在响应请求,但数据却无人接管。
残留 key 如何清理,FLUSHALL 能否直接使用
即使 CLUSTER SLOTS 返回空,旧节点上仍可能存在残留 key(例如迁移中断、客户端绕过重定向直连写入等情况)。此时不能使用同步阻塞的 FLUSHALL,尤其是在生产环境:
- 应使用
FLUSHALL ASYNC或逐库执行FLUSHDB ASYNC,避免阻塞主线程 - 先连接旧节点执行
DBSIZE和KEYS *(仅适用于开发环境或小数据量)来确认残留 key 的量级 - 若节点已无业务流量,可先执行
CLIENT KILL TYPE normal清除所有非 pub/sub 连接,再执行 flush
真正安全的缩容流程,不是“把槽位迁走就结束”,而是“确认槽位已空、key 已空、进程已停、客户端连接已断”。少一步,都可能让你在半夜收到报警。
