zSet实现排行榜功能

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: zSet实现排行榜功能

一.写在前面

  • 最近做完直播的基础功能后,又多了很多相关的需求,其中有一个就是直播间分享榜单的功能,顾名思义就是:分享本直播间并成功拉用户进来的数量做一个排行。比如我分享了这个直播间,别人通过我分享的直播间链接点进来,那么这个人就是我邀请来的,我总共邀请了10个人,你总共邀请了6个人,他总共邀请了11个人。实时排名就是他>我>你。
  • 简单介绍了一下功能,其实就是个根据某个权重值做排行榜的功能。

二.介绍redis的zset

这里就不说具体的zset实现了(我太菜,不敢放肆,等我牛逼了我再写zset实现,估计n年后 ),总之为了速度和稳定性以及持久化,redis肯定是最合适的,而且redis又有zSet这种数据结构,那不用zSet岂不是浪费嘛。

首先简单说一下zSet:

  • Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。
  • 不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
  • 有序集合的成员是唯一的,但分数(score)却可以重复。 (这么专业的话我肯定是说不出来的,当然是网上找的啦)
命令 描述
ZADD key score1 member1 [score2 member2] 向有序集合添加一个或多个成员,或者更新已存在成员的分数
ZCARD key 获取有序集合的成员数
ZCOUNT key min max 计算在有序集合中指定区间分数的成员数
ZINCRBY key increment member 有序集合中对指定成员的分数加上增量 increment
ZINTERSTORE destination numkeys key [key …] 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中
ZLEXCOUNT key min max 在有序集合中计算指定字典区间内成员数量
ZRANGE key start stop [WITHSCORES] 通过索引区间返回有序集合成指定区间内的成员
ZRANGEBYLEX key min max [LIMIT offset count] 通过字典区间返回有序集合的成员
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT] 通过分数返回有序集合指定区间内的成员
ZRANK key member 返回有序集合中指定成员的索引
ZREM key member [member …] 移除有序集合中的一个或多个成员
ZREMRANGEBYLEX key min max 移除有序集合中给定的字典区间的所有成员
ZREMRANGEBYRANK key start stop 移除有序集合中给定的排名区间的所有成员
ZREMRANGEBYSCORE key min max 移除有序集合中给定的分数区间的所有成员
ZREVRANGE key start stop [WITHSCORES] 返回有序集中指定区间内的成员,通过索引,分数从高到底
ZREVRANGEBYSCORE key max min [WITHSCORES] 返回有序集中指定分数区间内的成员,分数从高到低排序
ZREVRANK key member 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序
ZSCORE key member 返回有序集中,成员的分数值
ZUNIONSTORE destination numkeys key [key …] 计算给定的一个或多个有序集的并集,并存储在新的 key 中
ZSCAN key cursor [MATCH pattern] [COUNT count] 迭代有序集合中的元素(包括元素成员和元素分值)

上面就是redis的zset相关的命令,项目中实际是不会这么写的,我们使用的RedisTemplate进行的redis操作

三.实现方式

介绍完zset,然后说一下功能实现思路,其实很简单。。。。。就是往zset里面塞数据


stringRedisTemplate.opsForZSet().incrementScore(key, member, incrementScore);

上面代码,其实就是reids命令的:ZINCRBY key increment member,描述:有序集合中对指定成员的分数加上增量 increment比如你要给某个直播间做排行榜,key就是直播间相关的key,member就是邀请人的标识(一般就是userId),incrementScore就是这个人邀请的人数自增量(这是我的业务的说法,具体大家根据自己需求理解,融会贯通哈,比如微博热搜排序,key就可以是小时榜/天榜/月榜,member是某一条热搜词条,incrementScore就是这个词条热度增量/权重增量) ,我觉得你们肯定理解我为啥直接用incrementScore,而不是add,所以把自增量直接塞进去redis-zset就完事了,有人通过邀请进来了你就往进塞一次,因为这个命令是incrementScore也就是自增类型的,所以你也不用担心刚开始的时候是否存在这个key(并发问题),如果调用incrementScore的时候这个key已经存在,那就score自增,如果不存在那就新增这个key,然后把自增量设置为初始值,天然的线程安全,redis牛逼!!!  然后根据我的业务来说,我的incrementScore自增量就是1,因为我邀请了1个人就+1,没啥特殊值,但比如你的业务是直播间但消费额排行,那你的incrementScore自增量就是本次消费的金额数,这点应该很好理解,这里只说redis操作哈,如果这些数据还要落mysql等数据库,那看情况操作就行,比如我们的业务还要判断同一个人点了两个邀请链接,只算第一个的,并且直播结束还要拉取分享榜前三名发奖励,所以存入redis-zset的时候要校验,最后还要落库到mysql,但其实mysql很快的哈,又不是那种上千万的级别,上千万那你分库分表也不就完事了,实在不行你发一条mq消息处理呗,这种业务,我觉得保证最终一致就行了。

分享榜数据和排行问题,zset全部帮我们解决了,我们只需要给里面填入数据就行,简单、高效、实用。

剩下的就是取数据了,取数据的话也是从zset取排行的有序集合数据:


stringRedisTemplate.opsForZSet().reverseRangeWithScores(key, start, end);

上面这个代码,首先reverseRangeWithScores 方法的意思是:从大到小从第start+1名开始取值,到第end+1名结束,并且返回结果带分数, 简单来说就是把得分从大到小排序,然后取前end+1名,这个是RedisTemplate的方法,如果是redis操作的话,那命令就是上面表格中的:ZREVRANGEBYSCORE key max min [WITHSCORES],描述:返回有序集中指定分数区间内的成员,分数从高到低排序,这个描述我感觉有点绕哈,但是仔细理解一下还是能理解的

举个例子哈,如果你要取排行榜前十名,那么调用上面方法的参数就是:


stringRedisTemplate.opsForZSet().reverseRangeWithScores("key", 0, 9);

这个方法就会返回排行榜前十名,这个方法返回结果是:Set>,一个Set,具体结构其实大概就是个Set,直接循环这个结果,就拿到了前十名的结果。看到这里还不了解返回结果数据结构的可以去debug一下看看这个数据结构,立马就懂哈。循环这个结果拿到的就是排好序的,舒服啊,直接再完善一下数据,比如查一下用户名啥的,这个看具体业务哈,然后返回结果完事,简单、高效、又不担心线程安全。

好了!!!写完收工,zset实现排行榜真的很不错。本篇主要写实现思路,具体代码不能贴给你们看哈,因为是我们的业务代码,我又懒的自己写一个,所以只说思路,其实也不难,排序和并发问题redis都做好了,那还要啥自行车。


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
6月前
|
存储 算法 NoSQL
探秘HyperLogLog:Redis中的基数统计黑科技
探秘HyperLogLog:Redis中的基数统计黑科技
323 0
|
2月前
|
存储 NoSQL API
7)深度解密 Redis 的有序集合(ZSet)
7)深度解密 Redis 的有序集合(ZSet)
38 0
|
6月前
|
存储 NoSQL Java
redis zset详解:排行榜绝佳选择
新发布的App中,搜索功能使用Redis的有序集合(ZSET)来显示四个热门搜索词。由于应用初期,热门搜索显示的是测试词汇,为提升专业形象,计划删除这些测试词。文章介绍了ZSET的特性,如有序性、唯一性和快速查找,并讲解了如何在命令行中操作ZSET。此外,还分享了利用ZSET实现热搜功能的思路,每次搜索时增加对应词的分数以实现排序。最后,提供了Java代码示例展示了如何在Redisson中操作ZSET数据,以及如何实现热搜词汇功能。
311 1
|
6月前
|
存储 Ruby
4、有序集合
4、有序集合
|
6月前
|
NoSQL Redis Python
使用Sorted Set制作排行榜
使用Sorted Set制作排行榜
135 0
|
6月前
|
存储 NoSQL 关系型数据库
Redis Sorted Set 底层实现原理深度解读与排行榜实战
Redis Sorted Set 底层实现原理深度解读与排行榜实战
97 0
|
12月前
|
NoSQL Redis
redis排行榜之日排行周排行设计
redis排行榜之日排行周排行设计
|
存储 NoSQL Redis
一步一步学习Redis——五大数据类型之有序集合(ZSet)的相关命令
一步一步学习Redis——五大数据类型之有序集合(ZSet)的相关命令
一步一步学习Redis——五大数据类型之有序集合(ZSet)的相关命令
|
机器学习/深度学习 NoSQL 关系型数据库
Redis系列七 - 实现排行榜功能
Redis系列七 - 实现排行榜功能
323 0
|
存储 NoSQL Redis
Sorted Set源码阅读,有序集合为何能同时支持点查询和范围查询
Sorted Set源码阅读,有序集合为何能同时支持点查询和范围查询
43 0