2013-06-20 193 views
3

与此类似,但需要对哈希而不是纯键的解决方案:How to atomically delete keys matching a pattern using Redis删除基于哈希键名散装Redis的哈希值

我有一大堆的散列有相似的前缀:“前缀:”

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

我需要一些如何循环遍历所有的redis哈希,并删除每个cc_XX子项的一些方法,并且正在寻找一种cli/lua的方式来做到这一点(对于任何一个都不是很好)。

任何意见将不胜感激。

回答

5

以下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测试)

+0

我应该澄清,我不需要操作是原子的。有没有简单的方法让它允许其他电话在运行时通过? – JesseP

+0

更新了我的答案。 –

+0

为了我的理解,该脚本正在执行以下操作? – JesseP

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客户端* -obj5”的等价物。但是,这在redis-cli中不起作用。

我发现通过BASH以下工作:

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

如果使用环境中的不同的Redis数据库,添加“-n X”开关,是在Redis的-CLI等同于“选择X” 。在这种情况下,选择数据库4:

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