Redis中的哈希槽怎么理解

张开发
2026/4/12 11:19:49 15 分钟阅读

分享文章

Redis中的哈希槽怎么理解
Redis 哈希槽Hash Slot详解从零理解 Redis Cluster 的数据分片核心在 Redis Cluster集群模式中哈希槽是实现数据分片、高可用与线性扩展的基石。很多开发者刚接触集群时对“16384 个槽”、“槽位路由”、“节点宕机如何迁移”等概念感到困惑。本文将用通俗的语言 流程图 实例彻底讲清哈希槽的设计思想与工作原理。一、为什么需要哈希槽单个 Redis 实例的内存、吞吐量有上限。为了存储更多数据、支撑更高 QPS自然想到将数据分散到多个 Redis 节点—— 这就是分布式分片。分片面临三个核心问题数据如何均匀分布到不同节点客户端如何知道某个 key 应该去哪个节点访问节点增减/故障时如何尽量减少数据迁移哈希槽正是 Redis Cluster 解决上述问题的答案。二、哈希槽的基本概念Redis Cluster 将整个数据空间固定划分为16384 个哈希槽Hash Slot编号从0到16383。核心公式hash_slot CRC16(key) % 16384CRC16(key)对 key 进行循环冗余校验得到一个 16 位整数0~65535对 16384 取模结果必然落在 0~16383 之间为什么是 16384Redis 作者解释过16384 是一个适中的数字每个槽的元数据用 2KB 的 bitmap 即可描述16384 bits 2KB且能满足绝大多数集群规模最大 1000 节点平均每个节点 16 个槽。三、节点与槽的映射关系每个 Redis 节点负责一部分连续的或不连续哈希槽。例如一个 3 节点的集群可能分布为节点负责的哈希槽范围Node A0 – 5460Node B5461 – 10922Node C10923 – 16383集群内部维护一个槽→节点的映射表每个节点都知道所有槽分别由谁负责通过CLUSTER NODES命令可查看。可视化槽分布示例33%33%33%哈希槽分布示例 (3节点)Node A (0-5460)Node B (5461-10922)Node C (10923-16383)四、数据路由流程正常情况当客户端发送一个命令如GET mykey时流程如下负责该槽的节点任意节点入口客户端负责该槽的节点任意节点入口客户端1. GET mykey2. 计算 CRC16(mykey) % 16384 52003. 查本地槽映射表槽5200由 NodeB 负责4. 返回 MOVED 5200 127.0.0.1:63795. 重定向到 NodeB 执行 GET mykey6. 返回结果注意如果客户端一开始连接的就是正确节点则直接返回数据无 MOVED 重定向。智能客户端如 JedisCluster会缓存槽映射减少重定向次数。五、故障转移节点宕机时哈希槽如何处理Redis Cluster 的高可用依赖于主从架构每个主节点负责若干槽并配有至少一个从节点。当主节点宕机时是是否主节点 M1 宕机集群中超过半数主节点认为 M1 失联?从节点 S1 发起选举获得多数主节点投票?S1 晋升为新的主节点S1 接管 M1 原来的所有槽集群恢复槽映射更新集群标记 M1 为 FAIL但暂不切换核心点槽是绑定在主节点上的逻辑单元主节点故障后其从节点会原封不动地继承那些槽客户端无需感知槽位的变化只需获取新的 MOVED 重定向。如果某个槽既没有主节点也没有从节点所有相关节点全挂则整个集群不可用 —— 因为一部分数据无法访问。六、节点扩容/缩容时的槽迁移增加或删除节点时哈希槽需要在节点间重新分配并且槽内的 key 也要随之迁移。迁移过程简化源节点导出槽目标节点导入槽逐个迁移key迁移完成更新集群槽映射Redis 提供了CLUSTER SETSLOT、CLUSTER GETKEYSINSLOT等命令以及redis-cli --cluster rebalance工具来平滑迁移。迁移过程中客户端访问正在迁移的槽时可能会收到ASK重定向与MOVED类似但属于临时状态。七、哈希槽 vs 一致性哈希对比项一致性哈希如 Redis Cluster 前的老方案Redis 哈希槽数据分片方式哈希环 虚拟节点固定 16384 个槽节点增减影响范围只影响相邻节点但数据迁移粒度较粗精确控制每个槽的迁移元数据大小虚拟节点映射表可能较大16384 长度的 bitmap极紧凑实现复杂度较高需维护环较低槽映射清晰客户端路由需计算哈希并查找环计算槽位查表即可哈希槽的优势简单、确定性强、迁移粒度可控、元数据极小每个节点只需知道 2KB 的位图即可描述全部槽的归属。八、常见面试题与解答问Redis Cluster 中一个 key 到底存在哪个节点答先对 key 做 CRC16 取模得到槽号再根据集群内部槽→节点映射表找到负责该槽的主节点。问为什么哈希槽数量是 16384而不是 65536 或其他答16384 刚好是 2^14每个槽用 1 bit 表示归属16384 bits 2KB。若用 65536 bits 8KB心跳包会更大且 Redis 节点数量通常不会超过 100016384 个槽足够均匀分配。问如果客户端缓存了槽映射但集群发生了故障转移或重新分片会怎样答客户端按旧映射访问节点时节点会返回MOVED错误并告知新地址。智能客户端会更新本地缓存下次直接访问正确节点。问能否手动将某个槽从一个节点移到另一个节点答可以。使用CLUSTER SETSLOT slot NODE node_id命令但需要先迁移槽内的所有 key否则会丢失数据。生产环境推荐使用redis-cli --cluster reshard。九、代码示例计算 key 的槽位# Python 示例计算任意 key 属于哪个哈希槽defget_slot(key):importbinascii# 模拟 Redis CRC16 实现实际 Redis 有自己的 CRC16 查表算法crcbinascii.crc_hqx(key.encode(utf-8),0xFFFF)returncrc%16384print(get_slot(user:1001))# 输出例如 4210print(get_slot(order:2024))# 输出例如 12987在 Redis 客户端中可以直接使用CLUSTER KEYSLOT key命令查看CLUSTER KEYSLOT user:1001(integer)4210十、总结哈希槽是 Redis Cluster 的数据分片基础固定 16384 个槽通过CRC16(key) % 16384映射。每个槽由唯一一个主节点负责可以迁移给其他节点扩容、缩容、故障转移。客户端访问流程计算槽 → 查映射表 → 直接访问负责节点错误时收到 MOVED/ASK 重定向。高可用主节点宕机时从节点自动继承其槽并升级为主节点。对比传统分片方案哈希槽设计更简洁、元数据更小、迁移粒度精细。如果你正在搭建 Redis 集群请牢记槽均匀数据才均匀槽映射稳定集群才稳定。

更多文章