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 和生成的密钥是不是有效(如果我小心的话)?的主要内容,如果未能解决你的问题,请参考以下文章

redis lua脚本有啥用

redis集群不支持lua脚本吗

lua脚本~ Redis调用

Redis Lua脚本的详细介绍以及使用入门

如何在redis中华丽丽地使用lua脚本

lua在redis集群中的解决方案-- command keys must in same slot