核心方法
1. Hash Tag 方法(最常用)
原理 :使用 {
和 }
标记关键部分,只有大括号内的内容参与 slot 计算
示例:
redis
SET user:{123}:profile "John"
SET user:{123}:settings "premium"
SET order:{123}:pending "true"
规则:
- 只有第一个
{...}
对有效 - 可以出现在 key 的任何位置
- 大括号内至少应包含一个字符
- 无大括号时整个 key 参与计算
最佳实践:
- 选择具有业务意义的标识符作为 hash tag
- 保持 hash tag 简洁但足够分散
2. 手动计算 Slot(编程实现)
Java 实现:
java
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.util.JedisClusterCRC16;
public class RedisSlotUtils {
public static int getSlot(String key) {
return JedisClusterCRC16.getSlot(key);
}
public static boolean isSameSlot(String key1, String key2) {
return getSlot(key1) == getSlot(key2);
}
}
3. Lua 脚本方法
特性:
- Redis 保证脚本内的所有 key 会在同一节点执行
- 原子性操作保证
示例脚本:
lua
-- 原子性地更新用户数据和计数器
local userKey = KEYS[1]
local counterKey = KEYS[2]
local userData = ARGV[1]
local increment = ARGV[2]
redis.call('SET', userKey, userData)
return redis.call('INCRBY', counterKey, increment)
4. 事务处理方法
限制:
- 事务中所有 key 必须属于同一 slot
- 不支持回滚(遇到错误会继续执行后续命令)
示例:
redis
MULTI
SET user:1000:name "Alice"
SET user:1000:last_login "2023-01-01"
EXEC
其他方式
跨 slot 操作的解决方案
-
使用
HASH
类型:将相关数据存储在同一个 hash 中redisHMSET user:1000 name "Alice" last_login "2023-01-01" profile "..."
-
客户端聚合:对于 MGET 等操作,在客户端分组后分别请求
监控与验证工具
-
检查 key 所在 slot:
redisCLUSTER KEYSLOT "your_key"
-
查看集群 slot 分布:
redisCLUSTER SLOTS
-
强制操作特定 slot(高级用法):
redisCLUSTER COUNTKEYSINSLOT 1234
注意事项与最佳实践
性能考虑
- 避免热点:不要过度使用单一 hash tag 导致数据倾斜
- Tag 设计 :确保 hash tag 能均匀分布数据
- 好:
{user123}
、{order456}
- 不好:
{global}
、{common}
- 好:
维护建议
- 文档记录:明确记录使用的 hash tag 策略
- 一致性检查:定期验证关键数据是否位于预期 slot
- 迁移准备:设计可迁移的 key 命名方案
异常处理
- 当出现
CROSSSLOT
错误时,应:- 检查 key 设计是否符合 hash tag 规则
- 验证是否意外修改了 hash tag 部分
- 考虑使用 Lua 脚本重写相关操作
附录:常用命令参考
命令 | 描述 | 示例 |
---|---|---|
CLUSTER KEYSLOT |
查看 key 所属 slot | CLUSTER KEYSLOT user:1000 |
CLUSTER SLOTS |
查看集群 slot 分布 | CLUSTER SLOTS |
CLUSTER COUNTKEYSINSLOT |
统计 slot 中的 key 数量 | CLUSTER COUNTKEYSINSLOT 1234 |
通过合理应用这些方法和最佳实践,可以确保 Redis 集群模式下多 key 操作的正确性和高效性。