2011-01-30 22 views

回答

12

我認爲唯一的選擇是迭代排序後的集合並計算總和客戶端。

+0

謝謝!是的,我想這可能是Redis爲了執行...而特別設計的一個特性。因爲我甚至可能沒有做一些明智的事情。我使用zset來存儲用戶收到的禮品ID和發送用戶ID,SCORE是從同一個發件人收到同一禮品的次數。例如,`ZINCR 123:禮物1「3 | 345」`將來自用戶345的禮物w id 3發送給用戶123.因此,我希望得到用戶已收到的總禮物。看到?也許有更好的方法來實現這一點?這就像Facebook Gift API。 Redis規則! :)謝謝你的一切! – ma11hew28 2011-02-02 17:55:36

3

如果集合很小,並且不需要殺手級的性能,那麼我只需迭代(zrange/zrangebyscore)並對客戶端的值進行求和即可。

另一方面,如果您談論的是數千至數百萬個項目,您可以隨時爲每個用戶保留一個參考集合,然後在發送禮物時遞增/遞減總計。

所以,當你做你的ZINCR 123:gifts 1 "3|345",你可以做一個單獨的ZINCR命令,這可能是這樣的:

ZINCR received-gifts 1 <user_id> 

然後,得到的禮物#給定用戶接收到的,你只需要運行ZSCORE:

ZSCORE received-gifts <user_id> 
+0

增量計數贏得了迄今爲止的在線問題。掃描只能用於離線算法,恕我直言,因爲沒有人可以預測未來數據集的增長。這個答案應該是被接受的答案。 呵呵,順便說一句:有人可能會寫一個自定義命令,它可以同時執行這兩個操作(增加一個集合並遞增計數器;更新一個值並調整計數器,從集合中刪除......) – 2015-05-23 19:07:36

5

可用,因爲Redis v2.6是在Redis服務器上執行Lua腳本的最棒的能力。這使得一個有序集合的成績總結瑣碎的挑戰:

local sum=0 
local z=redis.call('ZRANGE', KEYS[1], 0, -1, 'WITHSCORES') 

for i=2, #z, 2 do 
    sum=sum+z[i] 
end 

return sum 

運行例如:

~$ redis-cli zadd z 1 a 2 b 3 c 4 d 5 e 
(integer) 5 
~$ redis-cli eval "local sum=0 local z=redis.call('ZRANGE', KEYS[1], 0, -1, 'WITHSCORES') for i=2, #z, 2 do sum=sum+z[i] end return sum" 1 z 
(integer) 15 
+2

一個重要的注意事項是Redis服務器-Lua腳本封鎖了一切,在大多數情況下這可能是一個破壞者。來源:http://stackoverflow.com/a/30896608/2440 – Sire 2016-12-20 08:32:23

1

這裏是一個小LUA腳本,當您去維持的zset成績總在一個櫃檯關鍵字後綴爲'.ss'。您可以使用它來代替ZADD。

local delta = 0 
for i=1,#ARGV,2 do 
    local oldScore = redis.call('zscore', KEYS[1], ARGV[i+1]) 
    if oldScore == false then 
     oldScore = 0 
    end 
    delta = delta - oldScore + ARGV[i] 
end 
local val = redis.call('zadd', KEYS[1], unpack(ARGV)) 
redis.call('INCRBY', KEYS[1]..'.ss', delta) 
+1

該腳本不應該在lua(`KEYS [1] ..'。ss'`)中構造密鑰,該密鑰違反了EVAL命令語義,腳本使用的密鑰應該使用KEYS數組傳遞「 - https://redis.io/commands/eval – Jonathan 2018-02-09 04:00:50