为什么说 Redis Cluster 终于把“迁移”这件事做对了?
在 Redis Cluster 的实际运维中,扩容、缩容、负载再均衡 是迟早会遇到的动作。问题不在于这些事情“能不能做”,而在于:能不能在不中断业务、不引入明显抖动、不增加客户端复杂度的前提下平稳完成。
长期以来,Redis Cluster 在 Slot 迁移这件事上,虽然具备可用能力,但始终存在一个现实问题:迁移过程本身,对线上业务并不完全友好。
Redis 8.4 引入的 **Atomic Slot Migration(ASM,原子化 Slot 迁移)**,正是为了解决这一问题而来。
它不是对原有 resharding 流程做一点“小优化”,而是从机制层面,重新定义了 Redis Cluster 在迁移 Slot 时的执行方式:从“逐 Key 搬迁、边迁边切”升级为“先复制、再一次性交接”。
这意味着:
- 扩缩容更平滑
- 热点 Slot 再均衡更可控
- 迁移期间客户端干扰显著减少
- 多 Key 操作与请求路径更稳定
- 迁移过程更适合真正的生产环境
如果你正在使用 Redis Cluster,或者负责 Redis 集群的交付、运维与架构设计,那么 Redis 8.4 的 ASM,是这次版本更新中非常值得重点关注的一项能力。
TL;DR:这次更新的核心价值是什么?
如果只用几句话概括 Redis 8.4 ASM 的意义,可以总结为:
- Redis Cluster 的 Slot 迁移终于具备“更接近生产级”的执行语义
- 迁移过程不再长期暴露“部分 Key 已迁、部分 Key 未迁”的中间态
- 客户端重定向、迁移期请求扰动与尾延迟尖峰显著降低
- 相比传统方式,Slot 迁移速度最高可提升约 30 倍
- Redis Cluster 在在线扩缩容与负载治理上的可运维性明显增强
换句话说,这次升级真正改善的,不只是“迁得更快”,而是:
让 Redis Cluster 在数据在线重分布时,更像一个成熟的分布式系统。
为什么 Redis Cluster 需要 Slot 迁移?
在理解 ASM 之前,先回答一个更基础的问题:
为什么 Redis Cluster 需要频繁迁移 Slot?
答案很简单,因为在 Redis Cluster 里,数据分布和节点负载本身就是动态变化的。
先理解一个核心概念:什么是 Redis Hash Slot?
Redis Cluster 使用 16,384 个 Hash Slot 来完成数据分布。
每个 Key 并不是直接绑定到某个节点,而是先根据哈希规则映射到某个 Slot,再由该 Slot 所属的节点负责存储和处理。
Redis 计算 Slot 的方式是:
暂时无法在飞书文档外展示此内容
如果 Key 中包含 {},则 Redis 只会对花括号内的内容做哈希。例如:
暂时无法在飞书文档外展示此内容
这两个 Key 会落在同一个 Slot 中,因此可以安全地参与同 Slot 的多 Key 操作。
这套设计带来的好处是:
- 数据可以自动分布到多个节点
- 集群可以横向扩展
- 每个节点只负责一部分 Slot
- 后续扩缩容时,可以按 Slot 粒度重新分配数据
也就是说,在 Redis Cluster 中,所谓“迁移数据”,本质上并不是“整台机器搬家”,而是:
把某些 Slot 以及其对应的数据,从一个节点迁到另一个节点。
哪些场景下需要迁移 Slot?
Redis 官方在这次更新说明里提到,Slot 迁移主要发生在两类场景。
1. 集群扩容与缩容
这是最常见、最标准的运维场景。
扩容:新增节点后,需要重新分摊数据和流量
当你向 Redis Cluster 中加入新节点时,新节点一开始并不会自动承载已有数据。
如果不迁移 Slot,新增节点就只是“挂在集群里”,并不能真正分担负载。
所以扩容真正需要完成的是:
把一部分 Slot 从旧节点迁到新节点,让新节点正式接手部分数据与流量。
缩容:下线节点前,必须先迁走其 Slot
反过来,当你要移除某个节点时,它当前持有的 Slot 不可能跟着一起消失。
在真正下线节点之前,必须先把这些 Slot 转移给其他节点。
因此缩容的本质是:
先完成 Slot 回收,再完成节点移除。
2. 节点负载不均衡,需要做在线再平衡
这类场景在真实生产环境中反而更常见。
因为 Redis Cluster 虽然能把 Key 分散到不同 Slot,但“Key 数量均匀”并不代表“资源消耗均匀”。
一个 Slot 是否“重”,取决于很多因素:
- 这个 Slot 里的 Key 是否偏大
- 是否承载了高频热点访问
- 写入是否集中
- 返回结果是否大
- 是否对应某个高流量业务域
因此你经常会看到这种现象:
- 某些节点内存特别高
- 某些节点 CPU 明显更忙
- 某些节点网络吞吐异常高
- 某些 Slot 成为热点 Slot
这时就需要通过迁移部分 Slot,把负载重新分散出去。
所以从工程角度看,Slot 迁移并不只是“调整分布”,更是:
Redis Cluster 的核心在线负载治理能力。
如何判断:哪些 Slot 需要迁移?
在很多团队里,Slot 迁移往往是“出了问题才做”。 但更理想的做法是:在问题变成故障之前,就具备识别不均衡的能力。
Redis 在这方面已经提供了比较实用的观测入口。
1. CLUSTER SHARDS:先看 Slot 当前分布
这个命令可以帮助你了解:
- 当前集群有哪些 shard
- 每个 shard 负责哪些 Slot
- 各节点主从关系如何
它解决的是“集群结构视角”的问题: 你先要知道 Slot 现在分布在哪些节点上。
2. CLUSTER SLOT-STATS:再看 Slot 的资源消耗
从 Redis 8.2 开始,Redis 引入了 CLUSTER SLOT-STATS,而在 Redis 8.4 中,这个命令的价值进一步提升。
它可以按 Slot 维度输出统计指标,包括:
KEY-COUNT:该 Slot 中的 Key 数量CPU-USEC:该 Slot 消耗的 CPU 时间NETWORK-BYTES-IN:该 Slot 接收的网络流量NETWORK-BYTES-OUT:该 Slot 发出的网络流量MEMORY-BYTES:该 Slot 占用的内存(Redis 8.4 起可用)
这里有一个非常值得强调的实践点:
真正决定是否需要迁移 Slot 的,不应该只是“Key 数量”,而应该是“资源消耗分布”。
例如:
- 某个 Slot 的 Key 不算多,但特别吃 CPU
- 某个 Slot 内存占用远高于平均值
- 某个 Slot 的网络出流量异常高
- 某个 Slot 持续成为业务热点
这类信息,才是做在线负载再平衡时最有价值的依据。
从这个角度看,Redis 8.4 的意义不只是“迁得更好”,还在于:
Redis Cluster 正在补齐按 Slot 维度做资源治理的观测能力。
Redis 8.4 之前,Slot 迁移为什么一直“不够优雅”?
在 ASM 出现之前,Redis Cluster 并不是不能迁 Slot。
你可以通过 redis-cli --cluster reshard、redis-cli --cluster rebalance,或者直接使用底层命令手动编排迁移流程。
问题在于:
旧机制虽然可用,但其执行语义本身并不适合“平滑在线迁移”。
这是理解 ASM 价值的关键。
传统迁移流程,本质上是“逐 Key 搬迁”
旧的 Slot 迁移流程,大致是这样:
- 在目标节点上把某个 Slot 标记为
IMPORTING - 在源节点上把这个 Slot 标记为
MIGRATING - 通过
CLUSTER GETKEYSINSLOT分批取出该 Slot 下的 Key - 使用
MIGRATE把这些 Key 一批批迁到目标节点 - 重复执行,直到这个 Slot 被搬空
- 最后再正式切换 Slot 所有权
看起来流程完整,但它有一个根本问题:
在迁移过程中,同一个 Slot 会长期处于“部分 Key 已迁、部分 Key 未迁”的中间态。
而生产系统最怕的,恰恰就是这种中间态。
旧迁移方式的核心问题,不只是“慢”
很多人对旧 Slot 迁移的第一印象是“比较慢”,但实际上,速度只是表象。
它真正的问题在于:
迁移过程会直接暴露到客户端行为、请求路径和数据语义层面。
下面几个问题,基本都源于同一个根因:迁移不是原子的。
1. 客户端必须处理迁移中的重定向
在旧机制下,某个 Slot 迁移过程中:
- 一部分 Key 已经迁到目标节点
- 另一部分 Key 还留在源节点
这时客户端访问某个已经迁走的 Key,Redis 会返回:
暂时无法在飞书文档外展示此内容
客户端必须额外跳转到目标节点重新请求。
这会带来明显的副作用:
- 客户端实现复杂度上升
- 请求链路变长
- 网络往返增加
- 延迟更不稳定
如果客户端对 Redis Cluster 迁移语义处理不充分,问题会在这类场景中集中暴露。
2. 多 Key 操作在迁移期间会变得不稳定
例如:
暂时无法在飞书文档外展示此内容
如果这两个 Key 虽然属于同一个 Slot,但其中一个已经迁走、另一个还没迁走,那么 Redis 可能返回:
暂时无法在飞书文档外展示此内容
这意味着:
迁移期间,多 Key 命令可能临时不可用或不可预测。
对于依赖批量读写、事务、Lua 脚本或多 Key 原子语义的业务来说,这种行为会显著增加线上不确定性。
3. 迁移失败时,容易留下难处理的“半完成状态”
旧迁移流程是“搬一批、删一批、再继续”。
如果中途出现异常,例如:
- 目标节点内存不足
MIGRATE超时- 网络抖动
- 迁移流程被中断
那么集群可能进入一种很尴尬的状态:
- 一部分 Key 已经到了目标节点
- 一部分 Key 还在源节点
- Slot 状态不一致
- 运维需要人工排查和修复
严重时甚至可能带来数据丢失风险。
这也是为什么很多团队在生产环境中对大规模 resharding 一直保持谨慎。
4. 逐 Key 迁移天然存在性能与延迟问题
传统迁移方式本质上是:
- 逐批查找 Key
- 逐批序列化
- 逐批网络传输
- 逐批反序列化恢复
这意味着它天然存在大量 **per-key overhead(逐 Key 固有开销)**:
- 额外查找成本
- 频繁网络往返
- 反复命令调度
- 持续状态扰动
所以它慢,并不是“实现不够优化”,而是:
方法本身就不适合高质量的在线迁移。
5. 大 Key 迁移更容易制造尾延迟尖峰
如果某个 Slot 中存在大对象,例如:
- 大 Hash
- 大 List / ZSet
- 大 JSON 文档
- 其他重型数据结构
那么使用 MIGRATE 时就更容易出现:
- 序列化耗时增加
- 反序列化耗时增加
- 网络传输负担加重
- 源 / 目标节点出现明显抖动
这类问题对线上系统的影响,往往不体现在平均值上,而体现在:
尾延迟(tail latency)突然飙高。
而这恰恰是生产环境最敏感的指标之一。
过渡:问题讲清楚了,接下来才轮到 ASM 真正登场
看到这里,你会发现 Redis 8.4 这次更新真正要解决的,不是“怎么把迁移命令再包装得更方便一点”,而是:
怎么让 Slot 迁移这件事,从“可用”变成“适合生产”。
而这,也正是 Atomic Slot Migration(ASM) 的核心价值所在。
在下篇中,我们会继续拆解:
- ASM 到底改变了什么
- Redis 8.4 如何使用
CLUSTER MIGRATION - ASM 在底层到底是怎么工作的
- 官方 benchmark 反映了哪些关键结论
- 为什么它不仅更快,而且更稳、更适合线上集群
下篇预告 |Redis 8.4 原子化 Slot 迁移详解
ASM 到底是怎么做到“更快、更稳、几乎无感迁移”的?
下篇我们将重点进入 Redis 8.4 ASM 的“实现与价值”部分,包括:
CLUSTER MIGRATION命令如何使用- ASM 的复制式迁移模型
- 原子切换是如何完成的
- Redis 官方 benchmark 应该怎么看
- 这项能力对生产运维到底意味着什么