如何用Redis实现排行榜及相同积分按时间排序功能


本篇内容主要讲解“如何用Redis实现排行榜及相同积分按时间排序功能”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何用Redis实现排行榜及相同积分按时间排序功能”吧! 需求:对组队活动中各个队伍的贡献值进行排行。Redis的Sorted Set是String类型的有序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数(score)却可以重复。免费云主机域名下面先不考虑积分相同的情况,实现排行榜:Redis默认实现是相同分数的成员按字典顺序排序(09,AZ,a~z),上面使用的是zrevrange,所以是倒序,所以相同分数排序就不能根据时间优先来排序。在上面的实现中,如果两个队伍的贡献值相同,也就是积分值相同,无法根据时间的先后进行排行。所以需要设计一个分数 = 贡献值 + 时间戳 ,谁分数大谁排前面,最后还要能根据分数能解析出来贡献值。使用整型存储分数值,redis中score本身是一个double类型,能精确存储的最大整型数字为2^53=9007199254740992(16位)。而精确到毫秒的时间戳需要13位,此时留给存储贡献值只有3位数了,当前如果时间只要精确到秒,只需要10位,这样留给贡献值就有6位。整体设计:高3位表示贡献值,低13位表示时间戳。如果我们简单地把score结构由:贡献值 * 10^13 + 时间戳 拼凑,因为分数越大越靠前,而时间戳越小则越靠前,这样两部分的判断规则是相反的,无法简单把两者合成一起成为score。但是我们可以逆向思维,可以用同一个足够大的数Integer.MAX减去时间戳,时间戳越小,则得到的差值越大,这样我们就可以把score的结构改为:贡献值 * 10^13 + (Integer.MAX-时间戳),这样就能满足我们的需求了。由于redis的score值是double类型,可以使用整数部分存储贡献值,小数部分存储时间戳,同样时间戳的部分使用一个最大值减去它。这样,整体设计变为:分数=贡献值 + (Integer.MAX-时间戳) * 10^-13弊端:由于分数值是由两个变量来计算得出,所以在给队伍增加贡献值时,无法简单的使用之前的zincrby来改变score的值了,这样在并发情况下为队伍增加贡献值就会导致score值不准确。错误情况模拟:假设现在队伍A的贡献值为10队伍A中的队员X为队伍增加贡献值1,在程序中算出score为11.xxx队伍A中的队员Y为队伍增加贡献值1,在程序中算出score为11.yyy队伍A中的队员X调用redis的zadd命令设置队伍的贡献值为11.xxx队伍A中的队员Y调用redis的zadd命令设置队伍的贡献值为11.yyy最后算出队伍A的贡献值为11,无法保证增加贡献值这一个操作的原子性。此时需要借助lua脚本来保证计算和设置贡献值这两个操作的原子性:由于redis中无法使用时间函数,所以(Integer.MAX-时间戳) * 10^-13部分由脚本外程序计算好传入。分页查询排行榜,查询队伍的排名等功能都可以继续使用上面的命令。所谓并列排行榜,就是存在相同排名情况的排行榜。我们期望的结果如下表:当然现实中也有排名不跳过的情况,我这里考虑的是排名跳过的情况。redis中score的设计还是采用上面的分数=贡献值 + (Integer.MAX-时间戳) * 10^-13,只是在查询排名时需要进行计算。比如要查上表中队伍b的排名,思路如下:首先查到队伍b的score再查到跟队伍b的score的整数部分相同(也就是贡献值一样),排在第一个的队伍的value(队伍ID)根据上一步得到的队伍ID查询此队伍的排名就是队伍b的排名使用命令实现上面的步骤如下:为了性能考虑,可以使用下面的脚本一次查出来:下面附上分页查询排行榜的脚本,假如一页10条,不用下面的脚本需要查询10次上面的脚本,如果连上面的脚本都没有使用的话就要查询30次redis。此脚本使用了cjson库,返回的是一个json。到此,相信大家对“如何用Redis实现排行榜及相同积分按时间排序功能”有了更深的了解,不妨来实际操作一番吧!这里是百云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

相关推荐: Redis哈希分片原理是什么

本篇内容介绍了“Redis哈希分片原理是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!如果Redis只用复制功能做主从,那么当数据量巨大的情况下,单机情况下…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 01/23 22:30
下一篇 01/24 18:20