Redis lua 脚本:集群时我尝试在脚本中混合 KEYS 和生成的密钥是不是有效(如果我小心的话)?
Posted
技术标签:
【中文标题】Redis lua 脚本:集群时我尝试在脚本中混合 KEYS 和生成的密钥是不是有效(如果我小心的话)?【英文标题】:Redis lua script: will my attempt to mix KEYS and generated keys within the script work when clustering (if I'm careful)?Redis lua 脚本:集群时我尝试在脚本中混合 KEYS 和生成的密钥是否有效(如果我小心的话)? 【发布时间】:2021-10-19 00:02:48 【问题描述】:我已经搜索过这个问题的答案,但每个问题并没有真正捕捉到我在问什么。
我正在使用 StackExchange.Redis 作为 C# 中的 redis 客户端,以在未来可能被集群化的 redis 缓存中维护状态。
我正在尝试使用 lua 脚本以原子方式管理数据集 - 集合的组合内容和其他关联键被组合以构建状态信息(我目前不能依赖 RedisJSON 来处理复杂数据) .
为了实现这一点,我有一个 lua 脚本,它在集合中搜索信息,并使用结果动态构建密钥,然后添加信息以维护其他密钥。
由于 Stackexchange.Redis 会使用传递给脚本的 KEYS 自动找到正确的节点来执行脚本,我想知道是否可以将两者混合以确保我的脚本是集群安全的。
我已经安排了我的密钥,以便脚本中的所有密钥都在同一个哈希槽中:
MyServiceName:id
例如:
redis.call SADD 'MyServiceName:1:namespaces', @namespace
redis.call SADD 'MyServiceName:1:namespace:' .. @ns .. 'providers', @providerId
请注意,这是一个简化的示例 - 我可能会将此处的所有键作为 KEYS 传递,但这会复制键和数据
我所做的如下:
(PerformOperation.lua)
-- Accept a dummy key that is in the same hash slot - this will ensure we are on the correct cluster node?
local idKey = @idKey
-- Do the rest of the stuff with only keys of the same hash slot
redis.call SADD 'MyServiceName:' .. @id .. ':namespaces', @namespace
...
(C# caller)
this.performOperationScript= this.LoadScript("PerformOperation.lua");
...
// The idKey defines the hash slot, for example MyServiceName:1
var result = await this.performOperationScript.EvaluateAsync(db, new idKey= $"MyServiceName:id", id );
这是否会达到我希望的效果,即 Stackexchange.Redis 会根据 idKey 将脚本转发到正确的集群节点,然后只要我在脚本中生成的任何密钥都在同一个哈希槽中,一切都应该正常吗?
提前致谢!
【问题讨论】:
【参考方案1】:Redis 使用 lua 时使用 KEYS 计算 slot。因此,如果您只有一个 IDKey 作为键,它将全部映射到正确的节点。
而且你的键是动态的并且你使用哈希标签,它会按照你的意愿工作。
【讨论】:
以上是关于Redis lua 脚本:集群时我尝试在脚本中混合 KEYS 和生成的密钥是不是有效(如果我小心的话)?的主要内容,如果未能解决你的问题,请参考以下文章