Redis:分类集中的SCORES总和

时间:2011-01-30 23:17:03

标签: sum redis sortedset

在Redis排序集中获取SCORES总和的最佳方法是什么?

4 个答案:

答案 0 :(得分:15)

我认为唯一的选择是迭代排序集并计算客户端总和。

答案 1 :(得分:11)

可用,因为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 :(得分:4)

如果集很小,而你不需要杀手性能,我会迭代(zrange / zrangebyscore)并对客户端的值求和。

另一方面,如果你谈论的是成千上万的项目,你可以随时为每个用户保留一个参考集以及运行总计,并在发送礼物时增加/减少它们。

所以,当你执行ZINCR 123:gifts 1 "3|345"时,你可以执行单独的ZINCR命令,这可能是这样的:

ZINCR received-gifts 1 <user_id>

然后,要获得给定用户的礼物数量,您只需要运行ZSCORE:

ZSCORE received-gifts <user_id>

答案 3 :(得分:1)

这是一个小的lua脚本,可以在一个带有后缀为&#39; .ss&#39;的键的计数器中保持zset得分总和。您可以使用它而不是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)