如何将Redis中的排行榜限制为仅限N个元素?

时间:2012-10-11 18:16:44

标签: algorithm nosql redis leaderboard

我需要创建一个具有最大元素数量的排行榜,比如N?我知道如何使用LPUSH + LTRIM将列表大小限制为N个元素。如何使用Redis sortedset

为排行榜实现此目的

到目前为止,我的方法是分3步完成: a)ZADD将分数+项添加到排行榜

b)找到第N个元素的等级(我不知道该怎么做)

c)做一个ZREMRANGEBYRANK排行榜0 rank_of_the_nth_element。

有更好的方法吗?

2 个答案:

答案 0 :(得分:7)

我实际上有一个使用redis的工作排行榜应用程序。你可以查看here。在我的应用程序中,排行榜受到最高n分数的限制,而且当他们年龄过大时,旧分数也会下降(因此可以有日,周,月,年高分榜)。

无论如何,我认为你要做的是一个整体的排行榜,所以低分被推掉了。在Redis Sorted Set分数的意义上,如果你设置了如此高分应该留下(它们在底部)并且低分应该离开(它们在顶部)然后你会做类似的事情:

ZREMRANGBYRANK leaderboard 0 -100

该示例假设您要保留最后100个分数。

也许你反转得分,所以1000的“高分”在redis中存储为-1000,所以它在排序集中的第一个。在这种情况下,它将与上面相同,但使用ZREMRANGEBYRANK leaderboard 100 -1删除前100个之后的所有项目。

更新:已实现ZREMRANGEBYRANK这样简化了我的例子。

您提出的解决方案也应该有效。如果要查找nth元素的分数,可以使用:

hundredth_entry = ZRANGE leaderboard 100 100
hundredth_score = ZSCORE leaderboard hundredth_entry
ZREMRANGEBYSCORE leaderboard -inf (hundredth_score

(是为了使范围不包含在内,所以除了百分之外的任何东西都将被删除,但不会删除百分数。

答案 1 :(得分:2)

OP算法的lua实现:

redis.call("ZADD", KEYS[1], ARGV[1]+0, ARGV[2])
local n = redis.call("ZCARD", KEYS[1])
if n > ARGV[3]+0 then 
    redis.call("ZREMRANGEBYRANK", KEYS[1], 0, n-ARGV[3]-1) 
end

然后替换

ZADD key score member

EVAL script 1 key score member cap