在 Redis Cluster 模式下,保证某个 key 始终落在同一个节点上的核心方法是 使用相同的 hash slot(哈希槽)计算规则。Redis Cluster 共有 16384 个哈希槽,每个 key 通过 CRC16 算法计算后取模分配到具体的槽位,而每个槽位由特定的节点负责。
1. 基本原理
- Redis Cluster 不直接按 key 分配节点,而是先计算
CRC16(key) % 16384
,得到该 key 所属的 hash slot(哈希槽)。 - 同一个 hash slot 一定由同一个节点管理。
- 目标:让多个 key 落在同一个 hash slot,从而保证它们存储在同一个节点。
2. 如何确保多个 key 落在同一节点?
(1) Hash Tag(哈希标签)
Redis Cluster 支持用 {}
定义“hash tag”:
- 只有
{}
内的内容参与 hash slot 计算。 - 不同 key,只要
{}
内的字符串相同,就会落到同一个 slot。
✅ 示例
# Key1: "user:{1000}:profile" → Hash Slot = CRC16("1000") %16384
SET user:{1000}:profile "Alice"
# Key2: "user:{1000}:orders" → Hash Slot = CRC16("1000") %16384
SET user:{1000}:orders "[...]"
这两个 key (user:{1000}:profile
, user:{1000}:orders
):
- Hash Tag =
1000
- 会分配到同一个 hash slot → 存储在同一节点
❌ 错误示范
# Key1: "user:1000:profile" → Hash Slot = CRC16("user:1000:profile") %16384
SET user:1000:profile "Alice"
# Key2: "user:1000:orders" → Hash Slot = CRC16("user:1000:orders") %16384
SET user:1000:orders "[...]"
这两个 key (user:1000:*
):
- 没有使用
{}
- Hash Slot ≠ (可能分布在不同节点)
(2) Lua脚本(事务/MULTI操作)
如果需要在集群模式下执行多键操作(如事务),可以使用:
-- EVAL script numkeys [key ...] [arg ...]
EVAL "redis.call('SET', KEYS[1], ARGV[1]); redis.call('EXPIRE', KEYS[1], ARGV[2])"
1
my_key
"my_value"
3600
⚠️ 注意:所有涉及的 KEYS 必须在同一节点!否则报错:CROSSSLOT Keys error
3. Redis Cluster Key分布优化建议
方法 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
Hash Tag ({xxx} ) |
需要强关联的 keys (如用户数据) | 简单高效 | 需谨慎设计 tag |
手动控制 slots (CLUSTER ADDSLOTS) | 特殊业务需求 | 完全可控 | 运维复杂 |
客户端分片 (Sharding) | 兼容旧代码 | 无侵入性 | 需额外维护 |
4. FAQ常见问题
❓ Q1:为什么有些命令在集群模式下不能用?
✅ Redis Cluster要求涉及多个key的命令必须属于同一slot。
❌ MGET/MSET/KEYS/SCAN/SINTERSTORE
等跨slot命令默认不支持。
✅解决方案:
# MGET替代方案(单slot)
MGET {user}:1 {user}:2
# SINTERSTORE替代方案(单slot)
SINTERSTORE result {tag}set1 {tag}set2
❓ Q2:如何查看某个key属于哪个slot和node?
# (a)计算Key的Slot ID:
redis-cli --cluster key-slot "my_key"
# (b)查看Slot分布在哪个Node:
redis-cli --cluster slots <HOST>:<PORT>
总结
✅ 最佳实践:
✔️ 对需要共存的 keys 使用相同的 Hash Tag ({xxx}
)
✔️ 避免跨slot的多key操作
✔️ 必要时用Lua脚本封装事务
🚀 这样就能确保相关数据始终落在同一Redis节点!
内容由零声教学AI助手提供,问题来源于学员提问