使用redis存key时,存到哪个主节点是怎么决定的
在 Redis 集群(Redis Cluster)中,数据存储的具体主节点由 哈希槽(Hash Slot)分配机制 决定。其核心流程如下:
# 🔑 1. 键值映射到哈希槽
Redis 集群预设了 16384 个哈希槽(Slot),每个键(Key)通过以下公式计算所属槽位:
Slot = CRC16(key) % 16384
1
- CRC16算法:计算键的哈希值(16位整数)。
- 取模运算:将哈希值对
16384
取余,得到槽位编号(0~16383)。
示例:
若键为user:1001
,计算CRC16("user:1001") = 12345
,则Slot = 12345 % 16384 = 12345
。
# ⚙️ 2. 槽位分配到主节点
集群初始化时,16384 个槽会被平均分配给所有主节点:
- 分配原则:每个主节点负责一段连续的槽范围(如 Node1 负责 0~5460,Node2 负责 5461~10922 等)。
- 动态调整:扩容或缩容时,槽位可通过命令迁移到新节点(如
CLUSTER ADDSLOTS
、CLUSTER SETSLOT
)。
关键特性:
槽位与节点的映射关系由集群内部维护,客户端无需硬编码节点信息。
# 📡 3. 客户端请求路由流程
客户端访问数据时,按以下逻辑定位目标节点:
- 本地缓存查询:
客户端(如 JedisCluster)缓存了槽位与节点的映射表。
根据键计算槽位,直接请求对应节点。 - 节点重定向:
- 若请求的节点不负责该槽,返回
MOVED
错误(含正确节点地址),客户端更新缓存并重试。 - 若槽位正在迁移中,返回
ASK
临时重定向,客户端需向目标节点发送ASKING
命令后再执行操作。
- 若请求的节点不负责该槽,返回
# 🔄 4. 节点变化时的处理
- 扩容/缩容:
槽位迁移期间,集群通过MOVED
/ASK
机制保证请求正确路由,客户端自动感知新拓扑。 - 主节点故障:
从节点接替槽位后,集群通过 Gossip 协议同步新映射关系,客户端通过重定向更新缓存。
# 💡 为何是 16384 个槽?
- 消息效率:集群心跳包需携带槽位分配信息,
16384
仅需 2KB 空间,而65536
需 8KB,更节省网络带宽。 - 分布均衡:足够多的槽数确保数据均匀分布,避免热点问题。
# ⚠️ 注意事项
- 键哈希优化:
使用哈希标签(如user:{1001}:profile
)可强制多个键映射到同一槽位,支持事务操作。 - 客户端要求:
需支持智能路由(如 JedisCluster、Lettuce),避免频繁重定向降低性能。 - 集群状态:
若槽位未完全分配(如节点宕机),集群可能拒绝请求,需配置cluster-require-full-coverage=no
避免全局不可用。
# ✅ 总结流程
graph LR
A[客户端写入 Key] --> B[计算 CRC16(key) % 16384 得到 Slot]
B --> C[查询本地槽位映射表]
C --> D{当前节点是否负责 Slot?}
D -- 是 --> E[执行写入]
D -- 否 --> F[返回 MOVED/ASK 重定向]
F --> G[客户端更新映射表并重试]
1
2
3
4
5
6
7
2
3
4
5
6
7
通过哈希槽机制,Redis 集群实现了数据分片、动态扩缩容和故障转移的自动化,开发者只需关注业务逻辑,无需手动管理数据分布。
编辑 (opens new window)
上次更新: 2025/06/24, 00:41:57