问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Redis - Zset 有序集合

创作时间:
作者:
@小白创作中心

Redis - Zset 有序集合

引用
CSDN
1.
https://blog.csdn.net/q322359/article/details/138217966

Redis的Zset(有序集合)数据结构是一个非常实用的功能,它结合了集合的唯一性特性和列表的有序性特性。本文将详细介绍Zset的各个方面,包括其与列表、集合的异同点,各种相关命令及其使用方法,内部编码方式,以及典型应用场景。

前言

Zset保留了集合不能有重复成员的特点,但与集合不同的是,有序集合中的每个元素都有一个唯一的浮点类型的分数(score)与之关联,有序集合中的元素是可以维护有序性的,但这个有序不是用下标作为排序依据而是用这个分数。

有序集合中的元素是不能重复的,但分数允许重复。类比于一次考试之后,每个人的学号不同,但分数可以相同。

列表、集合、有序集合三者的异同点

列表(List)、集合(Set)和有序集合(Zset)是Redis中三种不同的数据结构,它们各自具有独特的特点和适用场景:

  • 列表(List):有序的元素序列,可以添加、删除和获取元素。列表支持在两端进行快速插入和删除操作,适合实现队列和栈等数据结构。
  • 集合(Set):无序的元素集合,元素是唯一的。集合支持快速的成员检查、交集、并集和差集等操作,适合实现去重和关系运算。
  • 有序集合(Zset):结合了集合的唯一性和列表的有序性。每个元素都有一个关联的分数,元素按照分数进行排序。有序集合适合实现排行榜、优先级队列等场景。

命令

ZADD 添加或者更新指定的元素以及关联的分数

添加或者更新指定的元素以及关联的分数到 zset 中,分数应该符合 double 类型,+inf/-inf 作为正负极限也是合法的

ZADD 的相关选项:

  • XX:仅仅用于更新已经存在的元素,不会添加新元素。(当元素不存在则没有效果)
  • NX:仅用于添加新元素,不会更新已经存在的元素。(当元素存在则没有效果)
  • CH:默认情况下,ZADD 返回的是本次添加的元素个数,但指定这个选项之后,就会包含本次更新的元素的个数。
  • INCR:此时命令类似 ZINCRBY 的效果,将元素的分数加上指定的分数。此时只能指定一个元素和分数。

在未添加选项的情况下,ZADD 返回的是本次添加成功的元素个数,当元素不存在就创建,存在就更新分数

语法

ZADD key [NX | XX] [GT | LT] [CH] [INCR] score member [score member...]

时间复杂度:O(log(N))

返回值:本次添加成功的元素个数

ZRANGE 返回指定区间里的元素(分数按照升序)

带上 WITHSCORES 可以把分数也返回。分数按照升序,代表最小的数对应的下标为 0

语法

ZRANGE key start stop [WITHSCORES]

此处是 [start, stop] 为下标构成的区间. 从 0 开始, 支持负数.

时间复杂度:O(log(N)+M)

返回值:区间内的元素列表

ZREVRANGE 返回指定区间里的元素(分数按照降序)

带上 WITHSCORES 可以把分数也返回。分数按照降序,代表最大的数对应的下标为 0

语法

ZREVRANGE key start stop [WITHSCORES]

此处是 [start, stop] 为下标构成的区间. 从 0 开始, 支持负数.

时间复杂度:O(log(N)+M)

返回值:区间内的元素列表

ZRANGEBYSCORE 返回在指定分数范围内的元素

语法

ZRANGEBYSCORE key min max [WITHSCORES]

返回分数在 min 和 max 之间的元素,默认情况下,min 和 max 都是包含的,可以通过 ( 排除。

时间复杂度:O(log(N)+M)

返回值:区间内的元素列表

ZPOPMAX 删除并返回分数最高的 count 个元素

语法

ZPOPMAX key [count]

时间复杂度:O(log(N)*M)

返回值:分数和元素列表

BZPOPMAX 是 ZPOPMAX 的阻塞版本

语法

BZPOPMAX key [key ...] timeout

timeout 代表阻塞的最长时间,单位为秒,可以输入多个 key ,表示监控多个有序队列,当某个有序队列有元素就可以获取

时间复杂度:O(log(N))

返回值:元素列表

当监控的有序队列都没有元素时,那么该命令就会进入阻塞,直到有序队列中添加了元素或达到了最大阻塞时间,才能结束命令

ZPOPMIN 删除并返回分数最低的 count 个元素

语法

ZPOPMIN key [count]

时间复杂度:O(log(N)*M)

返回值:分数和元素列表

BZPOPMIN 是 ZPOPMIN 的阻塞版本

语法

BZPOPMIN key [key ...] timeout

timeout 代表阻塞的最长时间,单位为秒,可以输入多个 key ,表示监控多个有序队列,当某个有序队列有元素就可以获取

时间复杂度:O(log(N))

返回值:元素列表

当监控的有序队列都没有元素时,那么该命令就会进入阻塞,直到有序队列中添加了元素或达到了最大阻塞时间,才能结束命令

ZRANK 返回指定元素的排名(升序)

语法

ZRANK key member

时间复杂度:O(log(N))

返回值:排名

ZREVRANK 返回指定元素的排名(降序)

语法

ZREVRANK key member

时间复杂度:O(log(N))

返回值:排名

ZSCORE 返回指定元素的分数

语法

ZSCORE key member

时间复杂度:O(1) (因为开发者觉得该命令会经常使用,所以进行了优化,牺牲了空间来保证时间)

返回值:分数

ZREM 删除指定的元素

语法

ZREM key member [member ...]

时间复杂度:O(M*log(N))

返回值:本次操作删除的元素个数

ZREMRANGEBYRANK 按照排序删除指定范围的元素(升序)

语法

ZREMRANGEBYRANK key start stop

元素范围左闭右闭[ start,stop ]

时间复杂度:O(log(N)+M)

返回值:本次操作删除的元素个数

ZREMRANGEBYSCORE 按照分数删除指定范围的元素(升序)

语法

ZREMRANGEBYSCORE key min max

元素范围左闭右闭[ start,stop ]

时间复杂度:O(log(N)+M)

返回值:本次操作删除的元素个数

ZINCRBY 为指定的元素的关联分数添加指定的分数值

语法

ZINCRBY key increment member

时间复杂度:O(log(N))

返回值:增加后元素的分数

ZINTERSTORE 求出有序集合中元素的交集并保存进目标有序集合中

求出给定有序集合中元素的交集并保存进目标有序集合中,在合并过程中以元素为单位进行合并,元素对应的分数按照不同的聚合方式和权重得到新的分数。

语法

ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] 
[AGGREGATE <SUM | MIN | MAX>]

时间复杂度:O(NK)+O(Mlog(M)) N 是输入的有序集合中, 最小的有序集合的元素个数; K 是输入了几个有序集合; M 是最终结果的有序集合的元素个数.

返回值:目标集合中的元素个数

  • numkeys 是整数,描述了后面有多少个集合参与交集运算(之所以要说明集合个数,是为了避免与后面的选项产生歧义,知道个数以后,就能判断哪里是集合,哪里是选项)(类似粘包问题)
  • WEIGHTS 是权重,有序集合带有分数,此处指定的权重,相对于一个系数,会在求交集时,乘以当前的分数
  • AGGREGATE 表示求交集时,元素的分数按什么方式选择 (因为不同的集合中,相同的元素都有自己的分数),SUM 表示求和,MIN 表示取最小值,MAX 表示取最大值

例子

不带选项

默认不带选项的情况下,分数是相同元素的分数之和

带 WEIGHTS 权重选项

元素的分数会先乘以权重,再求和

带 AGGREGATE 选项

SUM 选项

和默认情况一样,元素的分数就是各个集合中对应元素的分数之和

MIN 选项

元素的分数就是各个集合中对应元素分数的最小值

MAX 选项

元素的分数就是各个集合中对应元素分数的最大值

ZUNIONSTORE 求出有序集合中元素的并集并保存进目标有序集合中

求出给定有序集合中元素的并集并保存进目标有序集合中,在合并过程中以元素为单位进行合并,元素对应的分数按照不同的聚合方式和权重得到新的分数。

语法

ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]] 
[AGGREGATE <SUM | MIN | MAX>]

ZUNIONSTORE 和 ZINTERSTORE 的选项含义完全一样,只是一个求并集,一个求交集,推荐看上面的 ZINTERSTORE 作为参考

内部编码

有序集合类型的内部编码有两种:

  • ziplist(压缩列表):当有序集合的元素个数小于 zset-max-ziplist-entries 配置(默认 128 个),同时每个元素的值都小于 zset-max-ziplist-value 配置(默认 64 字节)时,Redis 会用 ziplist 来作为有序集合的内部实现,ziplist 可以有效减少内存的使用。
  • skiplist(跳表):当 ziplist 条件不满足时,有序集合会使用 skiplist 作为内部实现,因为此时 ziplist 的操作效率会下降。

通过 object encoding 可以查看内部编码

使用场景

有序集合比较典型的使用场景就是排行榜系统。例如常见的网站上的热榜信息,榜单的维度可能是多方面的:按照时间、按照阅读量、按照点赞量。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号