Redis:排序集中的分数总和

发布于 2024-10-15 04:22:46 字数 39 浏览 2 评论 0原文

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

What's the best way to get the sum of SCORES in a Redis sorted set?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

疏忽 2024-10-22 04:22:46

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

The only option I think is iterating the sorted set and computing the sum client side.

可可 2024-10-22 04:22:46

自 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

Available since Redis v2.6 is the most awesome ability to execute Lua scripts on the Redis server. This renders the challenge of summing up a Sorted Set's scores to trivial:

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

Runtime example:

~$ 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
遗弃M 2024-10-22 04:22:46

如果集合很小,并且您不需要杀手级性能,我只需迭代(zrange/zrangebyscore)并对客户端的值求和。

另一方面,如果您正在谈论数千至数百万件物品,您始终可以保留一个参考集,其中包含每个用户的运行总计,并在发送礼物时增加/减少它们。

因此,当您执行 ZINCR 123:gifts 1 "3|345" 时,您可以执行单独的 ZINCR 命令,该命令可能如下所示:

ZINCR received-gifts 1 <user_id>

然后,获取给定时间收到的礼物数量用户,您只需要运行 ZSCORE:

ZSCORE received-gifts <user_id>

If the sets are small, and you don't need killer performance, I would just iterate (zrange/zrangebyscore) and sum the values client side.

If, on the other hand, you are talking about many thousands - millions of items, you can always keep a reference set with running totals for each user and increment/decrement them as the gifts are sent.

So when you do your ZINCR 123:gifts 1 "3|345", you could do a seperate ZINCR command, which could be something like this:

ZINCR received-gifts 1 <user_id>

Then, to get the # of gifts received for a given user, you just need to run a ZSCORE:

ZSCORE received-gifts <user_id>
蓝梦月影 2024-10-22 04:22:46

这是一个小 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)

Here is a little lua script that maintains the zset score total as you go, in a counter with key postfixed with '.ss'. You can use it instead of 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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文