登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  数据库 >  Redis

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 Cluster resharding 中 MOVED、ASK、TRYAGAIN 与槽位拓扑的静态关系说明图
图1:Redis Cluster 重定向信号的边界说明图;这是静态结构图,不是终端截图或运行证据。

让客户端先按槽位路由,再刷新拓扑

官方文档明确区分了基础的 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 Cluster 槽位地图、集群客户端拓扑缓存和有限重试策略的静态结构图
图2:槽位地图与客户端路由关系说明图,展示重定向处理边界,不表示实际执行顺序。

哪些方案适合排障,哪些不适合生产

临时排障时,redis-cli -c 很方便:它能让操作者看到请求被重定向到了哪个节点。但把普通单机客户端包在业务重试里,不会自动解决拓扑刷新、ASK 临时路由和多键操作边界。另一个常见错误是把重试次数设置得很大,表面上减少报错,实际上会把迁移抖动放大成线程池堆积。

更稳妥的判断是:能否缓存并刷新 slot map,能否区分 MOVED/ASK,能否对每个请求设置总超时和重试预算。如果这三项缺一项,就先换集群客户端或补齐适配层,再安排 resharding。

常见问题

resharding 期间出现 MOVED 是否一定要暂停迁移?

不一定。若客户端能刷新拓扑且重试率、超时和延迟仍在预算内,可以继续小窗口迁移;若出现持续重试或连接池耗尽,应先暂停并处理客户端路由。

ASK 能不能像 MOVED 一样更新 slot 表?

不建议。ASK 是迁移中的临时提示,当前命令跟随即可;只有确认稳定拓扑变化时,才把新的归属写入本地 slot map。

为什么增加重试次数后反而更慢?

每次重试都会消耗请求总预算和连接资源。迁移期间若多个请求同时重试,队列会进一步变长,所以应限制次数、加入短退避,并把最终失败交给降级逻辑。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>