我使用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 sorted set的默认实现,它按字典顺序返回排名。
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编程语言。
1条答案
按热度按时间7cjasjjr1#
排序后的集合首先按分数排序,然后按字典排序,这就是为什么你会得到不同的排序
user2
以及user3
.你可以合并
ZSCORE
,ZRANGEBYSCORE
以及ZRANK
使之正常化。基本上,你得到的分数user3
,然后按字典顺序获得第一个并列的用户,并获得该用户的排名。这给你一个排名,与领带排名相同,但留下差距排名。
如果你想你的排名没有差距,你可以保持排行榜与用户名单在一个给定的分数每个条目(
ZADD test-leaderboard 5 "user2,user3"
),或维护仅具有唯一分数的分离排序集。为了提高效率,我会选择第二个。添加新玩家
[O(log(N))]
:删除玩家
[O(log(N))]
:更新玩家分数
[O(log(N))]
:获得玩家的等级
[O(log(N))]
:几个注意事项:
使用
ZREVXXX
如果高分是最高级别,则发出命令。ZRANK
将最低分数排在第一位,使用ZREVRANK
如果你想把最高分排在第一位。看到了吗ZREVRANK
以及ZREVRANGEBYSCORE
.使用lua脚本
使用lua脚本,可以使操作原子化并更快地执行。
这里有一个例子。而不是
使用脚本:
用作: