集群哈希槽机制
什么是哈希槽
Redis Cluster 使用哈希槽(Hash Slot) 来管理数据分布。整个集群共有 16384 个哈希槽,编号从 0 到 16383。每个 Key 通过 CRC16 算法计算出哈希值后,对 16384 取模,决定它属于哪个槽:
slot = CRC16(key) % 16384
为什么是 16384 个槽
这个数字不是随意选的,而是经过精心设计的。作者 antirez 在设计中考虑了以下因素:
1. 心跳包大小控制
集群节点之间通过 Gossip 协议定期交换信息。每个心跳包中包含了节点的槽位信息(一个 bit 代表一个槽)。16384 个槽对应 2048 字节(16384 / 8 = 2048)的位图。
如果槽位数量太大(例如 65535 个),位图就会变成 8KB,导致心跳包变大,占用更多网络带宽。
2. 集群规模适配
16384 个槽对于最大 1000 个节点的集群已经足够。即使只有少数节点,每个节点也能分配到足够多的槽来实现良好的负载均衡。
3. CRC16 算法的输出范围
CRC16 算法输出 16 位(65536 个可能值),16384 正好是 65536 的 1/4,取模后的分布均匀性已经足够好。
哈希槽如何分配
每个主节点负责一部分哈希槽。例如一个 3 节点的集群:
节点 A:槽 0-5460
节点 B:槽 5461-10922
节点 C:槽 10923-16383
当需要扩展节点时,Redis 会从现有节点中移动一部分槽到新节点。槽迁移过程中,数据也会同步迁移。
Key 到节点的定位流程
正常情况
SET user:1001 "Alice"
↓
CRC16("user:1001") % 16384 → 计算出槽位 7256
↓
客户端本地缓存槽-节点映射表 → 槽 7256 在节点 B
↓
直接连接节点 B 执行命令
槽位变更(迁移/故障转移)
如果客户端请求的槽不在当前节点上,节点会返回 MOVED 重定向:
GET user:1001
↓
客户端连接到节点 A(但槽 7256 实际上在节点 B)
↓
节点 A 返回: -MOVED 7256 192.168.1.2:6379
↓
客户端更新本地缓存,重新连接到节点 B
Hash Tag:让多键操作跨槽
由于多键操作(MSET、MGET、事务、Lua 脚本)要求所有 Key 在同一个槽,Redis Cluster 提供了 Hash Tag 机制。如果 Key 中包含 {},则只对 {} 内的内容计算哈希:
user:{1001} → CRC16("1001") % 16384
order:{1001} → CRC16("1001") % 16384 ← 与上面相同!
这样,user:1001 和 order:1001 就会被分配到同一个槽,支持跨 Key 操作。
槽迁移过程
当增加或删除节点时,需要重新分配槽:
- 在目标节点上执行
CLUSTER SETSLOTIMPORTING - 在源节点上执行
CLUSTER SETSLOTMIGRATING - 源节点迭代槽中的所有 Key,逐个迁移到目标节点
- 迁移完成后广播槽归属变更
迁移过程中的 Key,如果被客户端访问,节点会返回 ASK 重定向(临时重定向,与 MOVED 不同),客户端需要先发 ASKING 命令再操作。
总结
哈希槽机制是 Redis Cluster 数据分布的核心。16384 个槽在集群规模扩展和心跳包大小之间取得了良好平衡。通过 CRC16 算法和槽映射,Redis 实现了数据的自动分片,同时通过 Hash Tag 提供了有限的多键操作能力。理解哈希槽机制对于掌握 Redis Cluster 的工作原理至关重要。


暂无评论内容