用redis中的Zset(有序集合)实现热度排行版及场景示例

2023-06-01 00:00:00 示例 有序 热度

排行榜功能我一般会使用redis中的Zset类型的有序集合数据结构来实现,非常方便。

Zset类型(Sorted Set,有序集合): 

可以根据元素的权重来排序,我们可以自己来决定每个元素的权重值。

比如说,我们可以根据元素插入Sorted Set的时间确定权重值,先插入的元素权重小,后插入的元素权重大。

在面对需要展示最新列表、排行榜等场景时,如果数据更新频繁或者需要分页显示,可以优先考虑使用 Sorted Set。

有序集合比较典型的使用场景就是排行榜。

例如学生成绩的排名榜、游戏积分排行榜、视频播放排名、电商系统中商品的销量排名等。


我们以博文点赞排名为例,发表了五篇博文,分别获得赞为 200、40、100、50、150。


示例代码:

# arcticle:1 文章获得了200个赞
> ZADD user:zongscan:ranking 200 arcticle:1
(integer) 1
# arcticle:2 文章获得了40个赞
> ZADD user:zongscan:ranking 40 arcticle:2
(integer) 1
# arcticle:3 文章获得了100个赞
> ZADD user:zongscan:ranking 100 arcticle:3
(integer) 1
# arcticle:4 文章获得了50个赞
> ZADD user:zongscan:ranking 50 arcticle:4
(integer) 1
# arcticle:5 文章获得了150个赞
> ZADD user:zongscan:ranking 150 arcticle:5
(integer) 1


文章arcticle:4 新增一个赞

可以使用 ZINCRBY 命令(为有序集合key中元素member的分值加上increment):

> ZINCRBY user:zongscan:ranking 1 arcticle:4
"51"


查看某篇文章的赞数

可以使用 ZSCORE 命令(返回有序集合key中元素个数):

> ZSCORE user:zongscan:ranking arcticle:4
"50"


获取文章赞数最多的 3 篇文章

可以使用 ZREVRANGE 命令(倒序获取有序集合 key 从start下标到stop下标的元素):

# WITHSCORES 表示把 score 也显示出来
> ZREVRANGE user:zongscan:ranking 0 2 WITHSCORES
1) "arcticle:1"
2) "200"
3) "arcticle:5"
4) "150"
5) "arcticle:3"
6) "100"


获取100 赞到 200 赞的文章

可以使用 ZRANGEBYSCORE 命令(返回有序集合中指定分数区间内的成员,分数由低到高排序):

> ZRANGEBYSCORE user:zongscan:ranking 100 200 WITHSCORES
1) "arcticle:3"
2) "100"
3) "arcticle:5"
4) "150"
5) "arcticle:1"
6) "200"


拓展知识

ZRANGEBYSCORE

是Redis 有序集合(Sorted Set)提供的一个命令,用于按照元素权重(score)区间范围查找有序集合中的元素。

其语法和用法如下:

ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]

其中,key 表示需要查询的有序集合键名;min 和 max 是两个区间值(闭区间),表示元素权重的最小值和最大值;

WITHSCORES 参数表示是否在结果中包含对应元素的分数值(可选);

LIMIT 参数用于限制返回结果的偏移量和数量(可选)。


具体实现时,

Redis 内部使用的是跳表(Skip List)数据结构来保存有序集合,以快速实现基于排名和范围的元素查询、插入和删除操作。

而 ZRANGEBYSCORE 命令即利用这一特性,在跳表结构中根据指定的区间范围,查询出符合条件的元素值列表。

其主要流程为:

1.根据指定的键名获取需要查询的有序集合
2.在有序集合中查找最小值和最大值对应的排名 min_rank 和 max_rank
3.从 min_rank 开始扫描每个节点,直到满足以下条件:第一个 score 值大于等于 min。记录下对应的排名 start_rank
4.同样从 max_rank 开始扫描每个节点,直到满足以下条件:第一个 score 值小于等于 max。记录下对应的排名 end_rank
5.返回位于 start_rank 和 end_rank 之间(包含边界值)的元素值列表。

注意:

在多数情况下,使用ZRANGEBYSCORE命令会返回有序集合中score值在指定区间中的全部元素,

这一过程时间复杂度为 O(log(N)+M),其中 N 表示有序集合总共的元素数量,而 M 表示查询结果的元素数量。

因此,在实际使用该命令时,应避免对过大的数据集进行范围查询,以免影响Redis数据库的性能和可用性。

相关文章