MOVED 表示键已永久迁移到新节点,客户端须解析响应中的槽位和目标地址,更新本地映射并重试一次;ASK 则为临时迁移状态,仅本次跳转且不更新映射。

MOVED 错误到底意味着什么
客户端收到 MOVED 响应,不是服务端出错了,而是 Redis Cluster 明确告诉你:“这个 key 不归我管,去 192.168.1.10:7001 找”。它带两个关键信息:目标节点的 IP:PORT 和该 key 对应的槽位(slot)编号。不解析这个响应、直接重试原命令,只会反复撞墙。
常见错误现象:
- 客户端持续向同一节点发请求,每次都被返回
MOVED 12345 192.168.1.10:7001 - 手动用
redis-cli -c连接时没加-c(cluster mode),结果报错后卡住 - 自研客户端忽略
MOVED,当成普通错误处理,导致数据写到错误节点或丢失
客户端必须自己实现重定向逻辑
Redis Cluster 不代理请求,也不做透明转发。客户端得主动解析 MOVED,提取目标地址,建立新连接(或复用已有连接),再重发命令。这不是可选项,是协议强制要求。
实操建议:
- 所有对 key 的操作(
GET、SET、HGET等)都需先计算 slot:slot = CRC16(key) & 16383 - 维护一份本地 slot → node 映射表,初始通过
CLUSTER SLOTS获取,后续靠ASK/MOVED动态更新 - 遇到
MOVED时,更新本地映射,并跳转到新节点重试——注意:只重试一次,避免无限跳转 - 不要每次请求都重新
CLUSTER SLOTS,它开销大,且集群拓扑变更不频繁
ASK 和 MOVED 的区别不能混淆
ASK 和 MOVED 都是重定向响应,但语义完全不同:MOVED 表示“永久迁移”,该 slot 已归属新节点;ASK 是临时状态,表示“这个 key 正在迁移中,当前不在本节点,但也不确定是否已完全迁走”。
使用场景与处理差异:
- 收到
MOVED:更新 slot 映射表,后续所有同 slot 请求直连新节点 - 收到
ASK:仅本次请求跳转,不更新本地映射;下一次仍按原 slot 路由,可能再次收到ASK或变成MOVED - 某些客户端库(如 Jedis)会自动处理
ASK,但不会自动刷新 slot 表——这意味着你得自己监听CLUSTER NODES或周期性调用CLUSTER SLOTS
连接池和超时配置直接影响重定向稳定性
重定向过程多了一次网络往返 + 新建连接(或从池取连接),若连接池配置不合理,容易引发雪崩:大量线程卡在等待新连接,或超时后抛异常而不是重试。
关键参数注意点:
-
maxTotal(连接池总数)要足够支撑并发重定向请求,否则会阻塞在getConnection() -
maxWaitMillis必须大于单次重定向耗时(通常 > 200ms),否则未等重试完成就超时 - 每个节点连接池要独立管理,不能共用一个池——否则
MOVED后取到的可能是旧节点的空闲连接 - 启用连接空闲检测(
testOnBorrow)能避免拿到已断连的 socket,但会增加延迟,权衡开启
重定向逻辑看似简单,但 slot 缓存一致性、ASK/MOVED 混合状态、连接池竞争这三处最容易漏掉细节。特别是当集群正在 resharding 时,ASK 和 MOVED 可能交替出现,这时候只依赖一次响应做判断,大概率路由错。










