用Redis怎么快速搞定排行榜前十名的查找和取数问题
- 问答
- 2026-01-08 21:37:38
- 10
要快速搞定排行榜前十名的查找和取数问题,Redis绝对是首选利器,因为它天生就是干这个的,核心思路就是用Redis的有序集合这个数据结构,你可以把有序集合想象成一个榜单,里面的每个成员(比如用户ID或者游戏玩家ID)都对应一个分数(比如用户的积分、游戏的得分),而且这个集合会自动根据分数从大到小或者从小到大排好序,这正是我们做排行榜需要的。
具体怎么做呢?我们从几个方面来直接说清楚。
第一,用什么数据结构?就用ZSET。
在Redis里,有序集合的命令都是以Z开头的,最关键的几个操作是:
- 添加或更新分数:
ZADD key score member,用户user1得了100分,你就执行ZADD leaderboard 100 user1,如果user1后来又得了50分,你再执行ZADD leaderboard 50 user1,Redis会很聪明地把他的分数更新为150分(默认是累加,你也可以设置成覆盖)。 - 查看排名:
ZREVRANK key member,这个命令能立刻告诉你某个成员在榜单里排第几名,注意,ZREVRANK是倒序排列,也就是分数从高到低排,排名从0开始,所以查询第一名返回的是0,如果你想看正序(分数从低到高)就用ZRANK,但排行榜一般用倒序。 - 查看分数:
ZSCORE key member,这个命令能立刻返回某个成员的具体分数是多少。
第二,怎么快速取前十名?一个命令搞定。
这是最核心的优势,当你把所有用户和分数都用ZADD添加进去之后,整个集合已经在内存里按分数排好序了,这时候,你要取前十名,只需要一个命令:
ZREVRANGE key 0 9 WITHSCORES
这个命令的意思是:在名为leaderboard的这个有序集合里,进行倒序排列(分数高的在前),然后取出从第0位到第9位(也就是前十名)的成员,并且把他们的分数也一起返回。
这个操作的速度非常快,是常数时间复杂度,也就是说,无论你的排行榜里有1万人还是1亿人,查询前十名所花的时间基本是一样的,因为Redis直接读取的是已经排好序的数据结构的头部,不需要临时计算。

第三,怎么处理相同分数的情况?
有时候会出现两个用户分数一样,那他们的排名怎么算?Redis的处理规则是:如果分数相同,则按照成员的字典序(lexicographical order)来排列,简单说,就是比较字符串的ASCII码,apple"会排在"banana"前面。
对于大多数排行榜应用来说,这个规则是可以接受的,如果你有特殊需求,比如希望分数相同的用户按照达到该分数的时间先后排序,你可以在设计分数时做点手脚,一个常见的技巧是:把实际分数和一个时间戳组合成一个新分数。
你的分数是整数,可以用一个非常大的数(比如10的10次方)减去时间戳(精确到毫秒),然后把这个计算出来的数字作为小数部分,加在实际分数后面。
假设用户A和用户B都得了100分,但A比B早达到,你可以这样:
用户A的分数做成:9999999999 (这里用9999999999模拟一个“大数-时间戳”的值,实际值会更长)
用户B的分数做成:0000000001
这样,虽然整数部分都是100,但因为A的小数部分更大,在Redis排序时,A依然会排在B的前面,取数的时候,你只需要取整数部分就是真实分数了,这个方法来自Redis官方文档和社区的最佳实践。
第四,除了前十名,还能做什么?

有序集合的功能很强大,除了查前十名,你还能轻松实现很多相关需求:
- 查看自己的排名和分数:用前面说的
ZREVRANK和ZSCORE。 - 查看前十名附近的人:比如你想看第8名到第12名,用
ZREVRANGE leaderboard 7 11 WITHSCORES就行了。 - 查看某个分数段的用户:比如你想看看所有积分在500分到800分之间的玩家,可以用
ZRANGEBYSCORE命令。 这些操作都非常高效。
第五,一个简单的例子
假设我们做一个游戏得分排行榜。
- 玩家1(uid:1001)得50分:
ZADD game_rank 50 uid:1001 - 玩家2(uid:1002)得80分:
ZADD game_rank 80 uid:1002 - 玩家3(uid:1003)得30分:
ZADD game_rank 30 uid:1003 - 玩家1又得了20分:
ZADD game_rank 20 uid:1001(此时uid:1001总分为70) 现在榜单里有三个玩家,分数分别是80,70,30。 - 查询前十名(虽然现在只有三个):
ZREVRANGE game_rank 0 9 WITHSCORESRedis会返回:- "uid:1002" (第一名)
- "80"
- "uid:1001" (第二名)
- "70"
- "uid:1003" (第三名)
- "30"
总结一下 用Redis做排行榜,核心就是使用有序集合(ZSET)。
- 更新数据用
ZADD,又快又方便,还能自动更新分数。 - 取前十名用
ZREVRANGE 0 9 WITHSCORES,一个命令瞬间完成,速度与数据量无关。 - 处理并列排名可以利用“分数+时间戳”组合的技巧。 这种方法简单、直接、高效,是经过大量实践检验的方案,你不需要关心底层是怎么排序和存储的,Redis都帮你做好了优化,你只需要调用几个简单的命令就行。
本文由歧云亭于2026-01-08发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://www.haoid.cn/wenda/77049.html
