根据散列键名批量删除redis散列值

Posted

技术标签:

【中文标题】根据散列键名批量删除redis散列值【英文标题】:delete redis hash values in bulk based on the hash key name 【发布时间】:2013-06-17 23:16:15 【问题描述】:

与此类似,但需要哈希而不是普通键的解决方案:How to atomically delete keys matching a pattern using Redis

我有一堆带有前缀的哈希,例如:“前缀:”

在每个散列下是一堆键,例如:“cc_XX”,其中“XX”是一个 2 个字母的代码。

我需要一些方法来遍历我所有的 redis 哈希,并以某种方式删除每个 cc_XX 子键,并且正在寻找一种 cli/lua 方法来执行此操作(两者都不是很好)。

任何建议将不胜感激。

【问题讨论】:

【参考方案1】:

以下EVAL script 应该做你想做的事:

local keys = redis.call('KEYS',KEYS[1])
for i,k in ipairs(keys) do
    local res = redis.call('HKEYS',k)
    for j,v in ipairs(res) do
        if string.find(v,ARGV[1]) then
            redis.call('HDEL',k,v)
        end
    end
end

您需要通过提供以下参数来调用它:

EVAL <script> 1 prefix:* cc_..

请注意,它会阻塞 Redis 事件循环,直到脚本完成,因此如果您有大量键,它可以冻结 Redis 一段时间。原子性是有代价的。

更新:

如果你不需要原子性,那么下面的脚本将避免阻塞 Redis 太长时间(但请注意,如果你有大量的全局键或者你的哈希对象之一很大,它仍然会阻塞:没有办法避免这种情况)。

./redis-cli keys 'prefix:*' | awk '
BEGIN 
    script = "local res = redis.call('\''HKEYS'\'',KEYS[1]); \
          for j,v in ipairs(res) do                          \
            if string.find(v,ARGV[1]) then                   \
              redis.call('\''HDEL'\'',KEYS[1],v);            \
            end                                              \
          end"


    printf "EVAL \"%s\" 1 %s cc_..\n", script, $1
' | ./redis-cli

(用 bash 测试)

【讨论】:

我应该澄清一下,我不需要原子操作。有没有简单的方法让它在运行时允许其他呼叫通过? 只是为了我的理解,脚本正在执行以下操作? 对不起,我在手机上写东西...我会试一试,并尝试了解您如何/为什么以这种方式编写脚本。我可能会向您发送另一个问题。 :) 我终于试了一下,似乎它删除了所有包含“cc_”的东西,而不是所有以“cc_”开头的东西。例如,我试图删除所有这些“cc_XX”键,同时保留所有新的键,例如“metadata_cc_XX”和“metadata_cc_XX_ts”,但在运行“cc_..”时它们都被删除了。任何建议将不胜感激。 啊哈,更多的正则表达式风格,我以为它只是带了一个通配符。谢谢!【参考方案2】:

我们在 Redis 中存储哈希的方式是,我们通过哈希中的对象类型为哈希元素 ID 键添加后缀。有时在数据模型中,我们更新一个对象,我们需要在部署时删除给定对象类型的所有哈希元素。我们希望在不删除整个哈希的情况下完成此操作。

例如:

127.0.0.1:6379> keys client*
1) "client"

127.0.0.1:6379> type client
hash

127.0.0.1:6379> hkeys client
 1) "123-obj1"
 2) "123-obj2"
 3) "123-obj3"
 4) "123-obj4"
 5) "123-obj5"
 6) "456-obj1"
 7) "456-obj2"
 8) "456-obj3"
 9) "456-obj4"
10) "456-obj5"

如果我们在应用程序中向 obj5 添加一个新字段并设置为默认值,我们将需要运行“HDEL client *-obj5”的等效项。但是,这在 redis-cli 中不起作用。

我通过 BASH 找到了以下作品:

redis-cli HKEYS 'client' | grep obj5 | awk ' printf "HDEL client %s\n", $1 ' | redis-cli

如果您在您的环境中使用不同的 Redis 数据库,请添加“-n X”开关,相当于 redis-cli 中的“select X”。在这种情况下,选择数据库 4:

redis-cli -n 4 HKEYS 'client' | grep obj5 | awk ' printf "HDEL client %s\n", $1 ' | redis-cli -n 4

【讨论】:

以上是关于根据散列键名批量删除redis散列值的主要内容,如果未能解决你的问题,请参考以下文章

Redis数据操作--散列键

Redis数据操作之字符串与散列键的区别 | Redis

Redis数据操作--字符串与散列键的区别

Redis常用命令 字符串键散列键

Redis-Hash常用命令

golang 根据keys获取的key列表批量删除