2013-06-20 205 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