Java 如何使用redis排序集实现竞争排行榜

Java 如何使用redis排序集实现竞争排行榜,java,redis,leaderboard,sortedset,Java,Redis,Leaderboard,Sortedset,我正在使用Redis排序集来维护我的游戏排行榜。我有一个场景,我需要保持与竞争排行榜得分相同的用户的排名。例如 | member | score | rank | — — — — — — — — — — — | member_1 | 50 | 1 | | member_2 | 50 | 1 | | member_3 | 30 | 3 | | member_4 | 30 | 3 | | member_5 | 10 | 5 | 到目前为止,我正在使用Redis排序集的默认实现,它按字典顺序返回排名

我正在使用Redis排序集来维护我的游戏排行榜。我有一个场景,我需要保持与竞争排行榜得分相同的用户的排名。例如

| member | score | rank |
— — — — — — — — — — —
| member_1 | 50 | 1 |
| member_2 | 50 | 1 |
| member_3 | 30 | 3 |
| member_4 | 30 | 3 |
| member_5 | 10 | 5 |
到目前为止,我正在使用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文档,没有这样的功能。所以我想知道我必须做什么,或者什么是实现此功能的最佳方式


注意:我的集合中有10K条记录,我需要在运行时维护它,我使用Java编程语言。

排序的集合首先按分数排序,然后按字典排序,这就是为什么
user2
user3
会得到不同的排名

您可以将
ZSCORE
ZRANGEBYSCORE
ZRANK
组合起来进行规范化。基本上,您可以获得
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 leadboard 5“user2,user3”
),或者维护一个仅包含唯一分数的单独排序集。为了提高效率,我会选择第二个

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

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

更新球员得分
[O(log(N))]

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

几点注意:

如果较高的分数为top rank,则使用
ZREVXXX
命令

ZRANK
将最低分数排在第一位,如果希望将最高分数排在第一位,请使用
ZREVRANK
。见和

使用Lua脚本

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

这里有一个例子。而不是

> ZSCORE test-leaderboard user2
"5"
> ZRANK test-ranks 5
(integer) 1
使用脚本:

local score = redis.call('ZSCORE', KEYS[1], ARGV[1])
return redis.call('ZRANK', KEYS[2], score)
用作:

> EVAL "local score = redis.call('ZSCORE', KEYS[1], ARGV[1]) \n return redis.call('ZRANK', KEYS[2], score)" 2 test-leaderboard test-ranks user2
(integer) 1

这回答了你的问题吗?我的问题有点不同,因为我试图在运行时完成它。而且我没有得到上面链接的解决方案,因为它使用Lua脚本。
> ZSCORE test-leaderboard user2
"5"
> ZRANK test-ranks 5
(integer) 1
> ZSCORE test-leaderboard user2
"5"
> ZRANK test-ranks 5
(integer) 1
local score = redis.call('ZSCORE', KEYS[1], ARGV[1])
return redis.call('ZRANK', KEYS[2], score)
> EVAL "local score = redis.call('ZSCORE', KEYS[1], ARGV[1]) \n return redis.call('ZRANK', KEYS[2], score)" 2 test-leaderboard test-ranks user2
(integer) 1