Redis分片集群插槽原理
一、前言为什么 Redis Cluster 不用一致性哈希很多分布式系统如 Memcached采用一致性哈希实现数据分片但 Redis Cluster 却另辟蹊径选择了“固定数量插槽 哈希取模”的方案。你是否曾疑惑为什么是16384 个插槽不是 1024 或 65536key 是怎么决定去哪个节点的为什么MGET key1 key2有时会报错本文将带你彻底搞懂 Redis 插槽Slot机制的设计思想与工作原理。二、插槽Redis Cluster 的分片单元2.1 核心概念Redis Cluster 将整个键空间划分为16384 个逻辑插槽slot编号从0到16383。每个 key 通过公式映射到一个 slotslot CRC16(key) % 16384每个 master 节点负责一部分插槽可以不连续客户端根据 slot 路由请求到对应节点✅优势分片规则简单、确定扩容时只需迁移部分 slot无需 rehash 全量数据节点增减对客户端透明自动重定向三、为什么是 16384深度解析设计权衡这是 Redis 作者antirez在 GitHub 上亲自回答的经典问题。3.1 官方解释精简“16384 是在消息大小、集群规模和内存开销之间取得的最佳平衡。”3.2 技术细节分析插槽数每节点心跳包大小支持最大节点数内存开销每节点65536~130 KB 100128 KB16384~32 KB~100032 KB4096~8 KB 10008 KB 关键原因心跳包不能太大Redis 节点每秒通过 gossip 协议广播集群状态包含每个 slot 的归属。若 slot 太多如 65536心跳包过大浪费带宽。slot 不能太少若只有 1024 个 slot当集群有 100 个节点时平均每个节点仅 10 个 slot负载极不均衡。16384 2^14足够大支持千级节点实际生产建议 ≤ 100足够小心跳包控制在 32KB 以内内存友好每个 slot 状态占 2 字节 → 总计 32KB结论16384 不是魔法数字而是工程实践中的最优解。四、Key 到插槽的计算流程4.1 标准计算公式slot CRC16(key) % 163844.2 特殊情况Hash Tag哈希标签Redis 支持通过{}强制多个 key 落在同一插槽user:{1001}:name→ 取{1001}计算 slotuser:{1001}:age→ 同样取{1001}→相同 slot✅用途解决 multi-key 操作跨 slot 问题如MGET,SUNION4.3 Java 示例计算 key 所属插槽public static int calculateSlot(String key) { // 1. 提取 Hash Tag String hashTag key; int start key.indexOf({); if (start ! -1) { int end key.indexOf(}, start 1); if (end ! -1 end start 1) { hashTag key.substring(start 1, end); } } // 2. CRC16 计算使用标准实现 int crc CRC16.crc16(hashTag.getBytes(StandardCharsets.UTF_8)); // 3. 取模 return crc % 16384; }五、客户端如何找到 key 所在节点5.1 首次访问MOVED 重定向客户端随机连一个节点如 7001节点计算 key 的 slot发现不在自己负责范围返回错误MOVED 5461 192.168.1.10:7002客户端缓存slot → node映射并重连 70025.2 扩容迁移中ASK 重定向当 slot 正在迁移源节点返回ASK 5461 192.168.1.10:7003客户端先发ASKING命令再发原命令✅Lettuce / Jedis Cluster 客户端自动处理这些重定向业务代码无感知。六、为什么多 key 操作会失败6.1 错误示例redis-cli -c MGET user:1 order:1 # (error) CROSSSLOT Keys in request dont hash to the same slot6.2 原因Redis Cluster要求所有 key 必须在同一插槽否则无法保证原子性。6.3 解决方案使用 Hash Tag# 强制落在同一插槽 MGET {user100}.profile {user100}.settings # ✅ 成功最佳实践对需要批量操作的数据使用相同 Hash Tag 前缀。七、插槽迁移与集群扩缩容7.1 扩容流程新增 master新节点加入集群CLUSTER MEET从现有节点迁移部分插槽到新节点客户端通过MOVED/ASK自动重定向迁移完成后集群负载更均衡7.2 迁移命令底层# 源节点执行迁移 key MIGRATE 192.168.1.11 7004 0 5000 KEYS key1 key2 # 更新插槽归属 CLUSTER SETSLOT 5461 NODE new-node-id⚠️注意迁移过程无需停机客户端可能短暂收到ASK。八、常用运维命令命令作用CLUSTER SLOTS查看所有插槽分配情况CLUSTER KEYSLOT key查询 key 所属插槽CLUSTER COUNTKEYSINSLOT 5461统计某插槽 key 数量CLUSTER GETKEYSINSLOT 5461 10获取某插槽的 10 个 key九、结语感谢您的阅读如果你有任何疑问或想要分享的经验请在评论区留言交流