Redis Cluster resharding 时怎样减少业务请求的 MOVED
来源:17golang原创
时间:2026-11-14 03:44:29 297浏览 收藏
Redis Cluster 做 resharding 时,业务请求偶尔出现 MOVED,不一定代表 Redis 故障。更常见的原因是客户端手里的槽位地图落后于集群配置:服务端告诉它“这个 slot 已经由另一台节点负责”,客户端刷新拓扑后再发送即可。要减少抖动,生产代码应使用集群感知客户端,缓存 slot 到节点的映射;迁移窗口内对 ASK、MOVED 和 TRYAGAIN 分开处理,并把重试次数、退避时间和超时设成有限值。
官方资料:https://redis.io/docs/latest/operate/oss_and_stack/management/scaling/
MOVED表示稳定的槽位归属变化,客户端应更新拓扑;ASK多见于槽正在迁移,不能直接替换成永久映射。- 生产客户端应直接按 slot 路由,只有地图过期时才刷新,避免每个请求都先问一个随机节点。
- resharding 采用小批量、可观察、有限重试的节奏,迁移完成后用集群检查和重定向指标收口。
先把 MOVED 和 ASK 分成两种信号
Redis Cluster 用 16384 个 hash slot 分片。客户端如果把请求发到了不负责该 slot 的节点,会收到类似 MOVED 12182 127.0.0.1:7002 的响应。它表达的是“当前拓扑里,这个 slot 的权威节点已经是另一个地址”,适合触发槽位地图更新。
resharding 的中间状态不同。源节点把 slot 标记为 MIGRATING,目标节点标记为 IMPORTING,键会逐步迁移;此时服务端可能返回 ASK,客户端应只把当前命令临时发往指定节点,并继续保留原有拓扑判断。把 ASK 地址永久写进 slot 表,会让迁移结束后的请求继续走错路。

让客户端先按槽位路由,再刷新拓扑
官方文档明确区分了基础的 redis-cli -c 和生产级集群客户端:前者会跟随重定向,后者通常会缓存 slot 到节点的映射,拓扑变化时再刷新。生产请求路径应优先走缓存地图,而不是每次先连接一个入口节点再等待 MOVED。
客户端配置可以按下面的思路落地:
| 信号 | 客户端动作 | 避免的误区 |
|---|---|---|
| MOVED | 刷新受影响的 slot 映射,限次重发 | 每次请求都全量刷新 |
| ASK | 当前命令临时跟随指定节点 | 把 ASK 永久写入拓扑 |
| TRYAGAIN | 短退避后有限重试 | 无限循环重试 |
| 超时/连接错 | 按网络故障和节点健康度处理 | 伪装成 MOVED |
示例配置采用伪代码表达策略,字段名需换成所用客户端的真实 API:
// 伪代码:展示集群重定向策略,字段名需按客户端适配
cluster := NewClusterClient(nodes,
WithTopologyRefresh(true), // 拓扑变化时刷新 slot 到节点的映射
WithMaxRedirects(3), // 限制 MOVED/ASK 的连续重定向次数
WithRetryBackoff(20*time.Millisecond), // 退避,避免迁移时形成重试风暴
)
result, err := cluster.Get(ctx, key)
if err != nil {
// 到达上限后交给上层降级或记录,不要无限重发同一请求
return fallbackOrReport(err)
}
return result
把 resharding 做成可观察的小窗口
redis-cli --cluster reshard 可以指定源节点、目标节点和槽数量;官方示例也支持用 --cluster-yes 做非交互执行。生产变更不要一口气移动全部计划槽位,建议先在低峰迁移一小段,观察客户端的 MOVED、ASK、TRYAGAIN、超时和 P99 延迟,再继续下一段。
迁移前记录源、目标、槽数量和业务峰值;迁移中看重定向率、重试耗时和错误分类;迁移后执行 redis-cli --cluster check ,确认槽覆盖和节点视图恢复。这个检查只能说明集群布局是否完整,不能代替业务侧的请求成功率监控。

哪些方案适合排障,哪些不适合生产
临时排障时,redis-cli -c 很方便:它能让操作者看到请求被重定向到了哪个节点。但把普通单机客户端包在业务重试里,不会自动解决拓扑刷新、ASK 临时路由和多键操作边界。另一个常见错误是把重试次数设置得很大,表面上减少报错,实际上会把迁移抖动放大成线程池堆积。
更稳妥的判断是:能否缓存并刷新 slot map,能否区分 MOVED/ASK,能否对每个请求设置总超时和重试预算。如果这三项缺一项,就先换集群客户端或补齐适配层,再安排 resharding。
常见问题
resharding 期间出现 MOVED 是否一定要暂停迁移?
不一定。若客户端能刷新拓扑且重试率、超时和延迟仍在预算内,可以继续小窗口迁移;若出现持续重试或连接池耗尽,应先暂停并处理客户端路由。
ASK 能不能像 MOVED 一样更新 slot 表?
不建议。ASK 是迁移中的临时提示,当前命令跟随即可;只有确认稳定拓扑变化时,才把新的归属写入本地 slot map。
为什么增加重试次数后反而更慢?
每次重试都会消耗请求总预算和连接资源。迁移期间若多个请求同时重试,队列会进一步变长,所以应限制次数、加入短退避,并把最终失败交给降级逻辑。
-
266 收藏
-
155 收藏
-
189 收藏
-
460 收藏
-
267 收藏
-
137 收藏
-
466 收藏
-
473 收藏
-
126 收藏
-
367 收藏
-
399 收藏
-
472 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习