在 Redis Cluster 模式下,Lua 脚本的 执行节点由传入的 KEYS
参数的哈希槽(Slot)决定。具体规则如下:
1. 关键结论
- 该脚本的执行节点由
KEYS[1]
的 Slot 决定(因为eval
命令的第3个参数是1
,表示只有KEYS[1]
被视为路由 Key)。 - 其他所有参数(包括
ARGV[...]
和其他KEYS[...]
)不会影响路由,但必须满足以下条件:- 所有被操作的 Key(即
ZREM
的目标 Key)必须与KEYS[1]
属于同一个 Slot,否则会报错:
-ERR CROSSSLOT Keys in request don't hash to the same slot
- 所有被操作的 Key(即
2. 代码分析
(1) EVAL 命令的参数结构
red_api:eval(
script, -- Lua脚本内容
1, -- KEY数量(此处为1,表示只有 KEYS[1] 是路由Key)
KEYS[1], -- 第一个Key(决定脚本执行节点)
KEYS[2], ..., -- 其他Key(需与 KEYS[1]同Slot)
ARGV[1], ..., -- ARGV参数(不影响路由)
sid -- ARGV[7]
)
(2) Lua脚本中的实际操作
脚本中通过 ZREM
操作了以下 Key:
redis.pcall("ZREM", KEYS[1], ARGV[7]) -- KEYS[1]
redis.pcall("ZREM", ARGV[1], ARGV[7]) -- ARGV[1]
redis.pcall("ZREM", ARGV[2], ARGV[7]) -- ARGV[2]
...
- 必须确保:
所有被操作的 Key(即KEYS[1]
,ARGV[1]
,ARGV[2]
, …,ARGV6]
) 属于同一个 Slot。
3. Hash Tag强制同Slot的方法
如果这些 Key 天然不属于同一 Slot,需要通过 Hash Tag(用花括号标记部分字符串)强制它们映射到同一 Slot。例如:
-- 示例:强制所有Key使用 {user123} 作为Tag
local sid = "user123"
red_api:eval(script,
1,
"myzset:{user123}", -- KEYS[1]
"arg_key1:{user123}", -- ARGV对应的实际值需替换为带Tag的Key
"arg_key2:{user123}",
...
)
4.错误排查建议
如果遇到跨 Slot错误:
检查所有被操作的 Key:确保它们通过 Hash Tag或自然分布属于同一 Slot。
日志调试:在调用前打印所有 Key,手动计算它们的 Slot:
# Redis命令行工具计算Slot redis-cli -c CLUSTER KEYSLOT "key_name"
总结回答你的问题
这段代码中,最终决定脚本执行节点的参数是 `KEYS [1]。其他所有被操作的 Key必须与它属于同一 Slot!
内容由零声教学AI助手提供,问题来源于学员提问