删除Redis集群中的多个键

时间:2019-12-30 12:32:40

标签: go redis redis-cluster

据我了解,redis集群中的插槽是分布式的,可以接多个键的DEL命令失败,并出现CROSSSLOT Keys in request don't hash to the same slot错误。

由于我现有的代码库是围绕批处理设计的,因此在相当多的地方调用redis缓存删除操作并列出要删除的键。由于更改此名称不是一个聪明的主意,因此我试图在我的缓存接口层找到一个解决方案,在那里我仍然可以接收要删除的多个密钥,并在此处添加所需的逻辑以达到相同的最终结果。我认为有两种选择需要

方法1。在按键上循环并使用Go例程+重量组

方法2。使用EVAL:我不确定这是正确的方向还是正确的使用。以下是

下的示例golang代码段
func (c CacheClient) Del(ctx context.Context, keysToBeDeleted []string) error {
    // _, err := c.client.Del(strings.Join(keysToBeDeleted, " ")).Result() // previously used when on single redis instance
    _, err := c.client.Eval("return redis.call('DEL', KEYS[1])", keysToBeDeleted).Result()

    if err != nil {
        // handle error
    }
    return nil
}

我创建了一个虚拟集群,并使用redis-cli来测试eval命令,如下所示

redis> EVAL "redis.call('del', KEYS[1]) " 2 mykey1, mykey2

此操作也失败,并显示CROSSSLOT Keys in request don't hash to the same slot错误。

我在Lua脚本中以错误的方式使用KEYS表吗?或者从集群中删除多个密钥的正确方法是什么。我应该坚持方法1吗?

使用Golang v1.13和redis.v5作为我的redis-client软件包。 如果有人可以使用redis.v5软件包本身来帮助我找到解决方案,那将更好。

1 个答案:

答案 0 :(得分:2)

我不确定使用Lua脚本是否可以帮助您。 Lua脚本对于强制执行原子性很有帮助,但是并不能帮助您克服多个插槽的问题。

针对您的问题的两种可能的解决方案是:

  1. 使用Redis hash tags。这意味着如果所有键中都有一个公共子字符串(例如["mykey_a", "mykey_b", ...]),则可以通过在公共子字符串({{1周围)加上花括号来强制Redis将所有键分组到同一插槽}})。显然,不建议对 all 的所有键使用相同的插槽,但是如果可以出于某些目的将其中的一些分组,则此解决方案是有效的。

  2. 使用Redis pipelines。这样,您可以分别执行每个["{mykey}_a", "{mykey}_b", ...]命令,但是可以保存网络RTT。 Go中的管道如下所示:

DEL