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