del-node前必须确保Slot迁出完成且旧节点无key残留,否则报错;需用node ID而非host:port迁移;del-node后须手动shutdown旧节点进程,并刷新客户端连接池。

del-node 执行前必须确保 Slot 迁出完成
Redis 集群缩容不是删节点就完事,del-node 本质是“驱逐”,它只检查目标节点是否还持有 Slot —— 只要还有任意一个 Slot 没迁走,命令直接报错:ERR Target node is not empty. All slots must be covered by other nodes.
常见错误是以为迁移命令发出去就等于完成了。实际上 redis-cli --cluster reshard 或 CLUSTER SETSLOT ... MIGRATING 只是发起迁移,真正数据同步、状态切换、槽位归属变更需要时间,且依赖客户端是否重定向、是否触发 ASK/MOVED 响应。
- 迁移完成后,务必用
redis-cli --cluster check <any-node></any-node>验证所有 Slot 是否被其他节点接管(输出里不能出现[ERROR] Slot XXX is not covered或xxx has slots but no keys类提示) - 更直接的方式是连上旧节点执行
CLUSTER SLOTS,返回结果应为空数组;再连上任意新节点执行CLUSTER NODES,确认旧节点状态为fail?或已消失 - 别跳过 key 清理:即使 Slot 已迁出,旧节点上仍可能残留 key(比如迁移中断、客户端写入未重定向),需手动执行
FLUSHALL ASYNC或逐库FLUSHDB ASYNC(注意:不是FLUSHALL同步阻塞)
reshard 迁移时指定 --to 节点 ID 而非 host:port
用 redis-cli --cluster reshard 迁移 Slot,交互式流程里要求输入 “target node id”,这里必须填目标节点的 40 位 ID(可通过 CLUSTER NODES 查),不能填 127.0.0.1:7001 或域名 —— 填错会导致迁移卡在 IMPORTING 状态,旧节点无法 del-node。
原因在于集群元数据只认 node id,host:port 是客户端连接信息,不参与 Slot 归属决策。填错后你看到的现象是:迁移命令看似成功,但 CLUSTER SLOTS 在旧节点仍显示该 Slot,新节点也无对应记录,整个 Slot 处于“悬空”状态。
- 查目标节点 ID:连任意节点执行
CLUSTER NODES,找 role = master 且是你想迁入的节点那一行,开头那串字符就是 ID - 批量迁移更稳:避免交互式操作出错,用非交互方式指定参数,例如:
redis-cli --cluster reshard 127.0.0.1:7000 --cluster-from <old-node-id> --cluster-to <new-node-id> --cluster-slots 100 --cluster-yes</new-node-id></old-node-id> - 注意 --cluster-slots 是指本次迁移的 Slot 数量,不是起始编号;如需精确控制哪些 Slot,得用
CLUSTER SETSLOT+MIGRATE手动逐个操作
del-node 后旧节点进程不会自动退出
del-node 只是让集群元数据剔除该节点,它对旧节点进程本身毫无影响 —— 进程照常运行,端口照常监听,只是不再被集群承认。如果此时不关进程,它会不断尝试重连集群,日志刷满 Connection refused 或 Node x.x.x.x:xxxx is not in cluster。
更麻烦的是:若误将旧节点配置保留在运维脚本或服务发现中,后续扩容或故障恢复可能意外把它拉回来,导致 Slot 冲突或数据不一致。
- 执行
del-node后,立刻在旧节点机器上执行redis-cli -p <port> shutdown</port>(注意加-p指定端口) - 确认进程已退出:
ps aux | grep redis | grep <port></port>应无输出;同时检查 systemd 或 supervisor 是否设了自动重启,如有,先 disable 对应 service - 别依赖“节点下线=服务停”:Redis 没有内置下线即停机制,一切靠运维主动收尾
客户端连接池没刷新会导致请求打到已 del-node 的节点
集群节点下线后,老客户端(尤其是用了长连接池的 Java/Go 客户端)可能还在往旧节点发请求,因为它们缓存了 CLUSTER NODES 结果或连接地址。现象是部分请求失败,报错类似 MOVED 123 127.0.0.1:7000(但 7000 已下线),或直接连接超时。
这不是 Redis 的问题,而是客户端没及时感知拓扑变更。Redis 本身只通过 MOVED 响应引导重定向,但客户端若忽略或缓存太死,就会持续错连。
- Jedis:确保使用 4.0+ 版本,并开启
refreshPeriod(默认 60s),或调用ClusterCommandExecutor.refreshNodes()强制刷新 - lettuce:启用
DynamicNodeProvider,并设置refreshTriggersReconnect和adaptiveRefreshTriggersTimeout - 最保险的做法:缩容窗口期,滚动重启客户端应用,而非依赖自动刷新
Slot 迁移和 del-node 只解决服务端视角,客户端连接池才是最后一公里。漏掉这步,缩容等于白干,还埋下间歇性故障隐患。

















