2016-07-06 35 views
1

我有一个由多个节点组成的redis集群。我想在单个原子操作中更新3个不同的键。我的Lua脚本是这样的:Redis集群:使用Lua脚本更新不同节点中的密钥

local u1 = redis.call('incrby', KEYS[1], ARGV[1]) 
local u2 = redis.call('incrby', KEYS[2], ARGV[1]) 
local u3 = redis.call('incrby', KEYS[3], ARGV[1]) 

和我一起放了一枪:

EVAL script 3 key1 key2 key3 arg 

但我得到WARN Resp(AppErr CROSSSLOT Keys in request don't hash to the same slot)。上述操作无法完成,更新将失败。看来我不能用一个Lua脚本修改不同节点中的密钥。但根据文档:

执行前必须分析所有Redis命令,以确定 命令将操作哪些键。为了确保EVAL为 ,必须明确传递密钥。这在很多方面都很有用, ,但特别要确保Redis群集可以将您的请求转发到 适当的群集节点。

注意这条规则并不是为了 向用户提供有机会滥用Redis的单 实例配置,在写剧本不兼容 与Redis的集群的成本执行。

所以我认为只要遵循按键传递规则,脚本应该与redis集群兼容。我想知道这里有什么问题,以及我应该如何更新单个脚本中的所有密钥。

回答

4

恐怕你误解了文档。 (我同意它不是很清楚。)

Redis操作,无论命令还是Lua脚本,只能在所有密钥位于同一台服务器上时才能使用。密钥传递规则的目的是让群集服务器找出脚本的发送位置,如果所有密钥不是来自同一个服务器(发生在您的案例中),则快速失败。

因此,您有责任确保您要操作的所有密钥位于同一台服务器上。要做到这一点的方法是使用散列标记强制密钥散列到同一个插槽。有关更多详情,请参阅the documentation

+0

我明白了。我使用群集的原因是希望不同的密钥在不同的节点中进行缩放。所以在这种情况下,我可能会放弃以原子方式更新密钥。非常感谢。 –

+0

很好的解释,谢谢! – Till

+1

也许我有点晚,但我有一个后续问题: 如果我确定未指定的密钥在同一个群集上,我仍然可以使用Lua脚本吗?所以我打破了必须指定所有密钥的规则,但遵循所有密钥都在同一台服务器上的规则。 – user3688217