redis集群扩容时查不到数据是因为槽迁移未完成,客户端仍按旧映射发送请求,目标节点尚未同步数据或未执行asking命令,导致返回moved/ask错误或nil;本质是客户端与服务端在迁移状态协同上的时序问题。

Redis集群扩容时为什么查不到数据
因为槽(slot)迁移过程中,目标节点尚未完成数据同步,而客户端仍按旧的哈希路由发请求,导致请求落到空节点或返回 MOVED 重定向失败。
典型现象是:部分 key 突然返回 (error) MOVED 12345 10.0.1.8:6379,但客户端没正确处理重定向,或者重定向后目标节点确实没数据——不是 bug,是迁移未完成的正常状态。
-
CLUSTER GETKEYSINSLOT在源节点能列出 key,但GET这些 key 时目标节点返回 nil,说明数据还在传输中,未 apply 到目标节点的 db - 客户端若缓存了 slot → node 映射(比如 Jedis、Lettuce 的默认模式),不会自动刷新,需收到
ASK响应后临时改用ASKING命令发请求 - 迁移进度可通过
CLUSTER NODES查看某节点的importing/migrating标志,以及CLUSTER COUNTKEYSINSLOT <slot></slot>对比源/目标节点数量
ASK 和 MOVED 响应的区别直接影响查找逻辑
MOVED 表示槽已永久归属新节点,客户端必须更新本地 slot 映射并重试;ASK 表示槽正在迁移中,当前请求可临时转向目标节点,但**不更新本地映射**,下一次同 slot 请求仍发给原节点。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 没加
ASKING前缀就向目标节点发命令,目标节点会拒绝并返回(error) ASKING required - Jedis 3.0+ 默认支持
ASK自动处理,但需确认配置了setReadFrom(ReadFrom.ASK)或启用clusterRedirectHandler - Lettuce 的
StatefulRedisClusterConnection会自动处理ASK,但前提是未禁用autoReconnect且未手动覆盖ClusterClientOptions中的重定向策略
为什么有些 key 在迁移中“消失”超过预期时间
不是网络或丢包问题,而是 Redis 的迁移粒度和阻塞行为导致的查找延迟:每次 MIGRATE 命令迁移一个 key,且是同步阻塞操作;大 key(如百万级 zset)会让单次迁移耗时数秒,期间该 slot 对应的所有 key 都无法被目标节点服务。
- 迁移速度受
cluster-node-timeout、网络 RTT、目标节点内存碎片率影响,但更关键的是migrate命令的COPY和REPLACE参数——不加REPLACE时遇到同名 key 会失败,中断迁移流 - 使用
redis-cli --cluster reshard扩容时,默认不启用--copy和--replace,容易卡在某个 key 上,建议显式加上:redis-cli --cluster reshard --copy --replace ... - 若业务对一致性敏感,应避免在迁移窗口期写入正在迁移的 slot,否则可能触发
LOADING错误(目标节点正在加载 RDB 片段)
如何验证迁移中的 key 是否真丢失还是只是暂时不可见
直接连源节点和目标节点分别查,比依赖客户端日志更可靠。
- 在源节点执行:
redis-cli -h src_ip -p 6379 CLUSTER GETKEYSINSLOT <slot> 10</slot>,再逐个GET确认存在 - 在目标节点执行同样命令,若返回空或 key 值为 nil,说明迁移未完成或失败;若返回
(error) LOADING Redis is loading the dataset in memory,说明 RDB 正在加载,需等待 - 检查
INFO cluster输出中的cluster_stats_messages_pong_sent和cluster_stats_messages_ask_received计数是否持续增长,可判断重定向链路是否通畅
ASK 是一次性的临时委派,而不是 slot 归属变更信号**——混淆这点,就会在扩容中途反复查不到 key。










