redis排序集相同的分数和不同的排名问题

问题描述 投票:0回答:1

我使用Redis排序集来维护我的游戏排行榜。我有一种情况,我需要保持分数相同的用户的相同排名。例如

127.0.0.1:6379> zadd test-leaderboard 9 user1
(integer) 1
127.0.0.1:6379> zadd test-leaderboard 5 user2
(integer) 1
127.0.0.1:6379> zadd test-leaderboard 5 user3
(integer) 1
127.0.0.1:6379> zadd test-leaderboard 3 user4
(integer) 1

如果查询user2和user3等级,则会得到不同的结果

127.0.0.1:6379> zrank test-leaderboard user2
(integer) 1
127.0.0.1:6379> zrank test-leaderboard user3
(integer) 2

我检查了Redis文档,没有这样做的功能。因此,我想知道我必须做什么或实现此功能的最佳方法是什么。

注意:我的SET中有1万条记录,我需要在运行时维护它,而我使用的是Java语言。

redis leaderboard sortedset
1个回答
0
投票

排序的集首先按分数排序,然后按字典顺序排序,这就是为什么user2user3的排名不同的原因。>>

您可以组合ZSCOREZRANGEBYSCOREZRANK对其进行标准化。基本上,您获得user3的分数,然后按字典顺序获得第一个用户,并获得该用户的排名。

> ZSCORE test-leaderboard user3
"5"
> ZRANGEBYSCORE test-leaderboard 5 5 LIMIT 0 1
1) "user2"
> ZRANK test-leaderboard user2
(integer) 1

这会给您一个等级,领带的等级相同,但排名之间有差距。

user4 => 0
user2 => 1
user3 => 1
user1 => 3

[如果您希望自己的排名没有差距,则可以按每个条目给定分数(ZADD test-leaderboard 5 "user2,user3")维护用户列表的排行榜,也可以仅保留唯一分数来维护单独的排序集。我会选择第二个以提高效率。

添加新玩家[O(log(N))]

ZADD test-leaderboard 5 user2
ZADD test-ranks 5 5

删除播放器[O(log(N))]

> ZSCORE test-leaderboard user2
"5"
> ZREM test-leaderboard user2
(integer) 1
> ZRANGEBYSCORE test-leaderboard 5 5 LIMIT 0 1
1) "anotherUser" or (empty list or set)
if(empty set)
> ZREM test-ranks 5

更新玩家分数[O(log(N))]

> ZSCORE test-leaderboard user2
"5"
> ZADD test-leaderboard 10 user2
(integer) 1
> ZADD test-ranks 10 10
(integer) 1
> ZRANGEBYSCORE test-leaderboard 5 5 LIMIT 0 1
1) "anotherUser" or (empty list or set)
if(empty set)
> ZREM test-ranks 5

获得玩家等级[O(log(N))]

> ZSCORE test-leaderboard user2
"5"
> ZRANK test-ranks 5
(integer) 1

一些注意事项:

如果分数最高则使用ZREVXXX命令

ZRANK将最低分数排在首位,如果要让最高分数排在首位,请使用ZREVRANK。参见ZREVRANKZREVRANK

使用Lua脚本

使用ZREVRANGEBYSCORE,您可以使操作原子化并更快地执行它们。

这里举个例子。代替

ZREVRANGEBYSCORE

使用脚本:

Lua scripts

用作:

> ZSCORE test-leaderboard user2
"5"
> ZRANK test-ranks 5
(integer) 1
© www.soinside.com 2019 - 2024. All rights reserved.