为什么我的 Redis Lua 脚本不能自动更新不同 Redis Cluster 节点上的键?

问题描述:

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

I have a Redis Cluster consisting of multiple nodes. I want to update 3 different keys in a single atomic operation. My Lua script is like:

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 脚本修改不同节点中的键.但根据文档:

The above operations cannot be done, and the updates will fail. It seems I cannot modify the keys in different nodes with a single Lua script. But according to the doc:

所有Redis命令在执行前都必须进行分析以确定命令将在哪些键上运行.为了做到这一点对于 EVAL,必须显式传递密钥.这在很多方面都很有用,但特别是要确保 Redis Cluster 可以将您的请求转发到合适的集群节点.

All Redis commands must be analyzed before execution to determine which keys the command will operate on. In order for this to be true for EVAL, keys must be passed explicitly. This is useful in many ways, but especially to make sure Redis Cluster can forward your request to the appropriate cluster node.

请注意,此规则不是按顺序执行的为用户提供滥用Redis单机的机会实例配置,代价是编写脚本不兼容使用 Redis 集群.

Note this rule is not enforced in order to provide the user with opportunities to abuse the Redis single instance configuration, at the cost of writing scripts not compatible with Redis Cluster.

所以我觉得只要遵循key传递规则,脚本应该是兼容Redis Cluster的.我想知道这里有什么问题,我应该怎么做才能在单个脚本中更新所有键.

So I think as long as I follow the key passing rule, the script should be compatible with Redis Cluster. I wonder what's the problem here and what should I do to update all keys in a single script.

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

I'm afraid you've misunderstood the documentation. (And I agree that it's not very clear.)

Redis 操作,无论是命令还是 Lua 脚本,只有当所有的键都在同一台服务器上时才能工作.密钥传递规则的目的是允许集群服务器确定将脚本发送到哪里,如果所有密钥都不是来自同一服务器(这就是您的情况),则快速失败.

Redis operations, whether commands or Lua scripts, can only work when all the keys are on the same server. The purpose of the key passing rule is to allow Cluster servers to figure out where to send the script and to fail fast if all the keys don't come from the same server (which is what happened in your case).

因此,您有责任确保要操作的所有密钥都位于同一服务器上.这样做的方法是使用 hash 标签 强制键散列到同一个槽.有关详细信息,请参阅文档.

So it's your responsibility to make sure that all the keys you want to operate on are located on the same server. The way to do that is to use hash tags to force keys to hash to the same slot. See the documentation for more details on that.