redis集群伸缩后数据迁移核心是槽的重新分配与键值平滑搬运,需先用add-node加入新节点(此时无槽),再通过reshard或rebalance显式迁移槽位,依赖getkeysinslot、migrate和setslot命令协同完成,客户端通过moved重定向自动适配。

直接用 redis-cli --cluster reshard 或 redis-cli --cluster rebalance 就能在线迁移,但必须确保新节点已加入集群且槽位未分配——否则命令会静默跳过,数据根本不会动。
新节点加入后必须手动分配槽位
执行 redis-cli --cluster add-node new_host:new_port old_host:old_port 只是让节点“入群”,它默认不持有任何槽(CLUSTER NODES 中显示 0-0 槽区间)。此时写入请求仍全部路由到老节点,新节点完全闲置。
- 必须显式触发槽迁移:用
redis-cli --cluster reshard进入交互式流程,指定源节点、目标节点、迁移槽数量 - 或用
redis-cli --cluster rebalance --cluster-threshold 1强制重平衡(--cluster-threshold默认为2,偏差小于2个槽不触发) - 若目标节点启用了 ACL,需提前在所有节点上运行
ACL SETUSER授权迁移所需权限(如+cluster,+keys)
迁移过程不是“复制整个槽”,而是键级搬运
Redis 不会把槽整体打包传输,而是按批次拉取键、逐个迁移、再更新槽归属。底层依赖三个命令协同:
-
CLUSTER GETKEYSINSLOT slot count:从源节点拉一批属于该槽的 key(注意count别设太大,否则阻塞主线程) -
MIGRATE target_host target_port key "" 0 1000:原子迁移单个 key(超时单位是毫秒,建议 ≥1000;空密码用"") -
CLUSTER SETSLOT slot NODE node_id:最终将槽归属关系广播到全集群(这步失败会导致客户端持续收到MOVED)
整个过程对客户端透明,但若某次 MIGRATE 失败(如网络抖动、目标节点 OOM),该 key 会留在原槽,需人工检查 CLUSTER KEYSLOT key + GET key 确认落点。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
验证不能只看槽分配,必须交叉查键实际位置
CLUSTER SLOTS 显示新节点分到了槽段,不代表数据真过去了。常见误判场景:
- 迁移中途被中断,槽归属已改但部分 key 没搬完 → 用
CLUSTER KEYSLOT key算出应属槽,再查CLUSTER SLOTS确认该槽当前归属节点 - 客户端缓存了旧的 slot 路由表(尤其 Jedis/lettuce 默认有本地 cache)→ 随机选几个 key 执行
GET,再用CLIENT LIST查响应连接的addr字段,确认是否连到新节点端口 - 目标节点内存不足,
MIGRATE返回NOAUTH或BUSY→ 检查目标节点INFO memory的used_memory_peak_human是否接近 maxmemory
redis-shake sync 模式更适合跨版本/跨云迁移
原生命令适合同版本、同环境集群内部伸缩;一旦涉及 Redis 7.0 → 云厂商托管集群(如阿里云 Tair、AWS ElastiCache),或需要增量同步,redis-shake 是更稳的选择:
- 配置里
source.cluster = true必须配全 master 节点列表(不能只写一个入口地址),否则它当单机处理,key 全写错 slot - 目标端若用 ACL,密码必须走
auth_password字段,不能塞进 URL(redis://:pwd@host:port在集群模式下部分节点会拒绝) - 同步中报
command not allowed或 key 消失,90% 是目标集群 slot 分布未就绪(比如CLUSTER SLOTS显示新节点有槽,但CLUSTER NODES里对应节点状态是fail或handshake)
真正麻烦的从来不是命令怎么敲,而是迁移过程中 slot 归属变更、客户端重定向、目标节点资源水位这三者的时序咬合——哪怕差几百毫秒,都可能让某个 key 卡在“旧路由未失效、新数据未落地”的缝隙里。










