导航菜单
首页 >  考研分数相同排名顺序  > 如何实现一个分数相同则按时间排序的排行榜?

如何实现一个分数相同则按时间排序的排行榜?

一、如何实现一个排行榜?

可以使用Redis的zset集合来实现一个排行榜,原因是zset集合可以将分数作为score、用户ID作为value,同时结合zset的排序功能,实现分数从高到低排序,相关的操作命令如下:

增加分数:zincrby查询TopN:zrevrange 0 withscores查询排行榜人数:zcard 查询指定用户排名:zrank+ 1查询指定用户分数:zscore …

查询TopN时,按照的是分数排序,如果分数相同,默认是使用value值做字典排序(如a>b,1>2),而不是按照时间排序。那么,如果想实现分数相同则按照时间排序应该怎么做呢?

二、如何实现分数相同则按照时间排序?

分析:由于查询TopN时是score越大排名越前,而我们想实现分数相同则按照时间排序,就需要结合时间戳来实现,而预期是插入时间越小排名越前(即分数相同时优先显示先插入的),跟score的规则是相反的解决方案:将分数当做score的整数部分,时间戳当做score的小数部分,查询结果里只取整数部分的分数即可,具体计算为

-- 初始score = 分数 + "." + 时间戳-- 改为数学运算score = 分数 + 时间戳 / 1^13-- 倒序处理,使时间戳越小,score越大score = 分数 + (1 - 时间戳 / 1^13)三、Q&A1、什么场景下要用到多个zset?

当需要设计一个多维度统计的排行榜时,就可能需要用到多个zset,比如我们有个每日签到打卡次数排行榜,除了总榜,还需要有日榜,所以设计如下:

查询用户日榜分数:zscore rank_20230901 查询用户总榜分数:zscore rank 查询用户近三日榜分数(交集):zunion rank_3_days 3 rank_20230901 rank_20230902 rank_20230903 weights 1 1 1…2、除了Redis,还有什么实现排行榜的方案吗?

除了Redis,还可以使用MySQL的order by语句进行排序,不过要注意性能问题,确保排序字段加上索引。Redis比较适用于数据量大、更新频繁、访问频繁的场景,MySQL比较适用于数据量小、使用不频繁的场景。

3、如何实现大于两个维度的多维度排序?

一般按照时间排序的话就只需要额外用到小数即可,但如果需要用到多维度比如用户等级、用户性别等,那么我们可以参考雪花算法来做(具体可参考文章《如何设计分布式ID?》)。

比如,我们定义score为10位,前5位为用户积分,中间3位为用户等级,最后1位为用户性别,那么最终的score就可能为8000010020,那么我们在排序的时候就会优先以前5位排序,如果前5位相同则按照中间3位排序,如果中间3位也想通则按照最后1位排序,这样就实现了榜单的多维度排序。

相关推荐: