一. 写在前面

  • 最近做完直播的基础功能后,又多了很多相关的需求,其中有一个就是直播间分享榜单的功能,顾名思义就是:分享本直播间并成功拉用户进来的数量做一个排行。比如我分享了这个直播间,别人通过我分享的直播间链接点进来,那么这个人就是我邀请来的,我总共邀请了 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<ZSetOperations.TypedTuple<String>>,一个 Set,具体结构其实大概就是个 Set<value,score>,直接循环这个结果,就拿到了前十名的结果。看到这里还不了解返回结果数据结构的可以去 debug 一下看看这个数据结构,立马就懂哈。循环这个结果拿到的就是排好序的<userId,score>,舒服啊,直接再完善一下数据,比如查一下用户名啥的,这个看具体业务哈,然后返回结果完事,简单、高效、又不担心线程安全。

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点 / 博客。

原始发表:2023-10-17,如有侵权请联系 [email protected] 删除

推荐

Redis 数据结构:Zset 类型全面解析

Zset,即有序集合(Sorted Set),是 Redis 提供的一种复杂数据类型。Zset 是 set 的升级版,它在 set 的基础上增加了一个权重参数 score,使得集合中的元素能够按 score 进行有序排列。

Redis 之 zset(sorted set)类型解读

Redis 有序集合 zset 与普通集合 set 非常相似, 是一个没有重复元素的字符串集合。不同之处是有序集合的每个成员都关联了一个评分 (score), 这个评分(score) 被用来按照从最低分到最高分的方式排序集合中的成员。集合的成员是唯一的, 但是评分可以是重复了

浅谈 Redis 的五大数据类型及其应用

Redis 是一种开源的内存数据结构存储系统,它支持多种数据类型,包括字符串 String、列表 list、集合、哈希表和有序集合。这些数据类型在 Redis 中有着广泛的应用场景,可以满足不同的业务需求。本文将介绍 Redis 的五大数据类型及其应用。

【Redis】五大常见的数据类型之 Zset

我们都知道 Redis 提供了丰富的数据类型,常见的有五种:String(字符串),Hash(哈希),List(列表),Set(集合)、Zset(有序集合)。

Redis 之 zset(sorted set)类型解读

Redis 有序集合 zset 与普通集合 set 非常相似, 是一个没有重复元素的字符串集合。不同之处是有序集合的每个成员都关联了一个评分 (score), 这个评分(score) 被用来按照从最低分到最高分的方式排序集合中的成员。集合的成员是唯一的, 但是评分可以是重复了

redis 入门 (一)

官方给出的读写速度可以达到 10W/s,以下是我本机双核四线程低压 i7 上测试的对字符串的读写速度。

Redis Sorted Set 底层实现原理深度解读与排行榜实战

Sorted Sets 与 Sets 类似,是一种集合类型,集合中不会出现重复的数据(member)。区别在于 Sorted Sets 元素由两部分组成,分别是 member 和 score。

Redis 面试(二):数据结构

String 是最常用的一种数据类型,普通的 key- value 存储都可以归为此类。其中 Value 既可以是数字也可以是字符串。使用场景:常规 key-value 缓存应用。常规计数: 微博数, 粉丝数。

你知道怎么基于 redis 实现排行榜吗

同事: 最近我在做一个在线游戏网站,需要实现一个排行榜功能,用来展示每个玩家的积分排名。

Redis 各类数据结构应用场景总结

实际面试过程中更多看重的是对 Redis 相关数据结构的活学活用,同时也可能会引申出 Redis 相关底层数据结构原理的实现,笔者最近面试过程中对这块内容有点生疏,所以本文也是为了笔者个人查漏补缺所写。

Redis 的数据结构 - 有序集合

该命令用于按照分数从小到大的顺序获取有序集合中指定范围的元素。可以选择是否同时返回元素的分数。

Redis 数据结构总结

Redis 本身是一个键值对数据库,这种键值对的存储方式就是哈希映射(Hashmap)的一种体现,即通过键(Key)来快速查找对应的值(Value)。

Redis 应用实践 - 排行榜

Redis 是一个高性能的内存数据库,其功能不仅仅限于简单的键值存储,还可以支持各种复杂的数据结构。其中,有序集合(Sorted Set)是 Redis 中一种非常有用的数据结构,可以用来实现排行榜、评分系统等功能。

Redis 数据类型

添加一个 string 元素到 key 对应的 set 集合中,成功返回 1,如果元素已经在集合中返回 0。

Redis 应用实践 - 排行榜示例

上面的代码首先连接 Redis 数据库,然后使用 zadd 命令向有序集合中添加元素,使用 zrevrank 命令获取元素的排名,使用 zscore 命令获取元素的分数,使用 zrevrange 命令获取排名前 N 的元素,使用 zrem 命令从有序集合中删除元素。

Redis 基础安装以及基本数据结构实战核心揭秘

全量遍历键,keys 用来列出所有满足特定正则字符串规则的 key,当 redis 数据量比较大时,性能比较差,要避免使用。

【Redis 基础】redis 基础知识总结——数据类型(字符串,列表,集合,哈希,有序集合)

  1. 根据 value 选择非阻塞删除,仅将 keys 从 keyspace 元数据中删除,真正的删除会在后续异步操作。

Redis 学习 - 入门篇

Redis 是一个支持网络交互的、可基于内存也可持久化的 Key-Value 数据库(非关系性数据库),它不仅性能强劲,而且还具有复制特性; Redis 提供了五种不同类型的数据结构,各式各样的问题都可以很自然地映射到这些数据结构上。

Redis 实现用户积分和积分排行榜微服务优化

在之前的博客中我通过 MySQL 数据库实现了积分和积分排行榜功能,在数据量大和并发量高的情况下会有以下缺点: