Redis Cluster 槽位迁移过程要注意什么?
简化版
槽迁移要把目标设为 IMPORTING、源设为 MIGRATING,分批迁移该 slot 的 Key,校验完成后再由集群节点一致更新 slot 所有权。迁移期间客户端必须正确处理 ASK 临时重定向和 MOVED 永久重定向;还要限速、防 Big Key 卡迁移、控制拓扑变更并验证源目标数据与业务延迟。
详细版
迁移不是简单拷贝:源节点对已迁走/不存在的 Key 可能返回 ASK,客户端应先向目标发送 ASKING 再执行一次命令,不能把它永久缓存;槽归属正式切换后返回 MOVED,客户端更新 slot map。迁移期间新写必须由协议正确落到源或目标,业务不要双写两个节点。
操作前检查集群健康、副本与容量、Big/Hot Key、客户端兼容和多 Key/hash tag;冻结其他拓扑变更。按小批 MIGRATE,设置合理超时与重试但避免无限重放;观察源/目标 CPU、内存、网络、P99、复制 lag 和重定向率。Big Key 应先治理或单独低峰迁移。
完成后向所有主节点传播新 owner,确认 CLUSTER SLOTS/SHARDS 一致、源无残留 Key、目标数据可读且副本追平。失败时根据阶段继续迁移或回滚槽状态,不能只改元数据留下数据分叉。
完整版教学
一、槽迁移的状态机
Redis Cluster 有 16384 个 slot。迁移 slot S 从 A 到 B 时,B 标记 S 为 importing from A,A 标记 S 为 migrating to B,然后逐 Key 搬迁。元数据状态告诉节点迁移中的请求该如何重定向。
准备:slot S owner = A
1. B: IMPORTING S FROM A
2. A: MIGRATING S TO B
3. 分批 MIGRATE keys in S
4. 所有主节点:slot S owner = B
5. 校验与清理迁移状态
记忆钩子:先建立迁移状态,再搬数据,最后切正式所有权;顺序错了会产生路由空窗或错误重定向。
二、ASK 与 MOVED 的语义差异
迁移期间,A 仍是官方 owner,但某个 Key 已经搬到 B。A 找不到该 Key 时可返回 ASK B,客户端仅本次请求向 B 发送 ASKING 后执行;它不应因此永久修改整个 slot 路由。
当集群正式把 slot owner 改为 B,访问 A 会得到 MOVED B,这表示长期拓扑变化,客户端应刷新/更新 slot cache。把 ASK 当 MOVED 会过早将尚未迁移的 Key 全送 B;忽略 MOVED 则会长期多一次重定向。
| 响应 | 阶段 | 客户端行为 |
|---|---|---|
| ASK | Key 迁移中 | 单次去目标,先发 ASKING,不永久改槽表 |
| MOVED | 槽所有权已变化 | 更新槽映射,必要时刷新拓扑 |
三、迁移命令与原子性边界
MIGRATE 可将 Key 序列化传到目标,成功后从源删除,支持批量 Key 与超时。它对单次 Key 迁移提供协议保证,但整个 slot 包含许多 Key,不是一个全局原子事务;迁移过程中源目标同时存在不同 Key 是正常状态。
客户端只应通过 Cluster 路由访问,业务自行对 A/B 双写会绕过迁移状态并制造冲突。Lua/事务涉及多个 Key 时要求同槽;迁移中的多 Key 命令更复杂,应在变更前识别并降低相关业务风险。
失败重试前要确认 Key 当前在哪一侧,命令与工具应幂等处理“源已无、目标已有”,不能盲目复制覆盖较新值。
四、Big Key 和 Hot Key 为什么危险
slot 迁移粒度是 Key。一个 5GB Key 无法像许多小 Key 一样平滑批量,单次序列化、网络和删除都可能超时并阻塞;Hot Key 迁移时并发访问产生大量 ASK 和额外网络跳转。
操作前按 slot 扫描 Key 大小、成员数和 QPS。Big Key 先业务拆分,无法立即拆则低峰单独迁移、调大单次超时并加强监控;Hot Key 可短时本地缓存、限流或选择业务低谷。不要因为 slot 总容量小就忽略其中单 Key 分布。
假设 10GB slot 中一个 Key 占 8GB,按 100MB/s 理论传输也需 80 秒,实际序列化与竞争更久;普通 1 秒超时必然失败。
五、限速与容量检查
迁移会同时消耗源读取/删除、目标写入、主从复制和网络。目标节点必须有数据内存、复制缓冲与 fork 余量;迁入后不能立刻达到 maxmemory 并淘汰。源目标的副本也会重放变化。
按批 Key 数或字节限速比只按 Key 数更合理,因为大小差异巨大。每批后观察 P99、CPU、网络、复制 lag、客户端重定向和业务错误,超阈值暂停。多个 slot 并行迁移要控制总带宽。
safe_migration_bandwidth
= min(source_spare, target_spare, network_spare, replica_spare)
若在线流量突然上升,迁移任务应主动让路,而不是与用户请求争夺资源。
六、拓扑变更必须串行协调
同一 slot 不应被两个任务同时迁往不同目标。迁移控制器需要任务 ID、拓扑版本、分布式互斥或单一控制面,并在每步验证预期 owner。扩容、缩容、故障转移同时发生时,原计划可能失效,应暂停并重新读取拓扑。
客户端拓扑刷新也会形成风暴。MOVED 处理可以局部更新并对全量刷新做合并/限频,避免数千客户端同时请求 cluster slots。旧版客户端必须提前做兼容测试。
迁移审计记录源、目标、slot、批次、字节、失败和操作者,支持中断后从已确认状态恢复。
七、完成校验与失败恢复
数据搬完后确认源 COUNTKEYSINSLOT 为 0、目标数量与抽样值正确,再向所有主节点设置 slot owner B。随后确认 cluster state、slot map、目标副本 offset 与业务命中率,清除残余迁移状态。
若中途失败,槽正式 owner 仍为 A 时通常可继续向 B 迁移,或把已迁 Key 反向迁回并清理状态;若 owner 已切 B,应以 B 为权威完成残留收口。不能只将 owner 改回却不处理 B 上新写。
slot: 7421
source: node-a
target: node-b
keys_remaining_source: 0
bytes_migrated: 12884901888
ask_rate: 0
target_replica_lag_seconds: 0
topology_consistent_nodes: 6/6
八、常见误区与追问
- 误区:迁槽只需要修改 slot owner。 数据尚在旧节点时直接切元数据会造成 miss 和错误重定向。
- 误区:ASK 表示客户端应永久更新路由。 ASK 仅针对迁移期单次请求,MOVED 才表示正式归属变化。
- 误区:slot 总内存不大就可以高速迁移。 Big/Hot Key、复制和在线带宽可能成为瓶颈,必须看分布。
- 误区:目标主节点有空间就够了。 还要考虑目标副本、缓冲、碎片和持久化峰值。
- 追问:迁移期间写请求会不会丢? 按 Cluster 协议和正确客户端路由可继续处理;业务自行双写或客户端不支持 ASK/MOVED 才容易出错。
- 追问:如何回滚半完成迁移? 依据正式 owner 决定方向,迁回已搬 Key 或继续收口,并同步清理迁移状态,不能只改元数据。
- 追问:为什么需要
ASKING? 目标尚非正式 owner,ASKING 允许它仅为该次被重定向请求访问 importing slot。
九、加强记忆
槽迁移按“目标导入、源端迁出、分批搬 Key、正式切 owner、校验副本”执行。ASK 是一次性迁移路由,MOVED 是永久拓扑更新;Big/Hot Key、目标容量和副本复制决定安全速度;失败恢复必须让数据位置与 slot 元数据重新一致,不能只在控制面点完成。