【Redis】Zset有序集合常用命令以及使用场景

news2024/10/9 22:24:15

Redis 的有序集合(Sorted Set,简称 Zset)是一个非常强大的数据结构,它结合了集合(Set)的唯一性和列表(List)的有序性。每个元素都关联一个评分(score),并且元素按照评分值从小到大排序。这种数据结构在许多场景中都非常有用。本文将深入探讨 Redis 的 Zset 数据结构及其常用命令和应用场景。

 有序集合(Zset)与普通集合(Set)的主要区别在于 Zset 中的每个元素都会关联一个分值(score)。Zset 通过分值对元素进行排序,并且支持范围查询和按分值范围的操作。这使得 Zset 非常适合处理需要排序的数据

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

1. 常用命令

1.1 普通命令

1. ZADD

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

  • NX:只添加新元素,不更新已存在的元素。
  • XX:只更新已存在的元素,不添加新元素。
  • GT:更新元素时仅在新分值大于当前分值时进行更新。
  • LT:更新元素时仅在新分值小于当前分值时进行更新。
  • CH:返回被修改的元素个数。
  • INCR:对成员的分值进行累加操作。
127.0.0.1:6379> ZADD myzset 1 "one" 2 "two" 3 "three"
(integer) 3
127.0.0.1:6379> ZADD myzset 2.5 "two"
(integer) 0

2. ZRANGE

返回有序集合中指定区间内的元素,默认按照分值从小到大排序。带上WITHSCORES可以把分数也返回。

语法ZRANGE key start stop [WITHSCORES]

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

127.0.0.1:6379> ZRANGE myzset 0 -1 WITHSCORES
1) "one"
2) "1"
3) "two"
4) "2.5"
5) "three"
6) "3"

3.  ZREVRANGE

语法ZREVRANGE key start stop [WITHSCORES]

  • key:有序集合的键。
  • start:起始位置(按逆序计数,从 0 开始)。
  • stop:结束位置(按逆序计数,可以使用 -1 表示最后一个元素)。
  • WITHSCORES(可选):如果指定此选项,则会将成员的评分值一并返回。

返回值

  • 默认情况下,返回指定范围内的成员列表,按评分值从高到低排序。
  • 如果使用 WITHSCORES 选项,则返回一个包含成员和评分值的列表。
127.0.0.1:6379> ZADD myzset 1 "one" 2 "two" 3 "three" 4 "four" 5 "five"
(integer) 5
127.0.0.1:6379> ZREVRANGE myzset 0 2 WITHSCORES
1) "five"
2) "5"
3) "four"
4) "4"
5) "three"
6) "3"

4. ZCARD

获取一个 zset 的基数(cardinality),即 zset 中的元素个数。

语法:ZCARD key

返回值:zset 内的元素个数。
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZCARD myzset
(integer) 2

5. ZCOUNT

返回分数在 min 和 max之间的元素个数,默认情况下,min 和 max 都是包含的。

语法:ZCOUNT key min max

返回值:满⾜条件的元素列表个数。
  • key:有序集合的键。
  • min:分值范围的最小值,可以是具体的数值,也可以是 -inf 表示负无穷。
  • max:分值范围的最大值,可以是具体的数值,也可以是 +inf 表示正无穷。
127.0.0.1:6379> ZADD myzset 1 "one" 2 "two" 3 "three" 4 "four" 5 "five"
(integer) 5
127.0.0.1:6379> ZCOUNT myzset 1 3
(integer) 3
127.0.0.1:6379> ZCOUNT myzset -inf +inf
(integer) 5

6. ZPOPMAX

语法ZPOPMAX key [count]

  • key:有序集合的键。
  • count:可选参数,表示要移除并返回的元素数量,默认值为 1。

返回值

  • 默认情况下,返回有序集合中具有最高评分的元素及其评分值。如果指定了 count,则返回 count 个元素及其评分值。
127.0.0.1:6379> ZADD myzset 1 "one" 2 "two" 3 "three" 4 "four" 5 "five"
(integer) 5
127.0.0.1:6379> ZPOPMAX myzset
1) "five"
2) "5"
127.0.0.1:6379> ZPOPMAX myzset 3
1) "four"
2) "4"
3) "three"
4) "3"
5) "two"
6) "2"

7. BZPOPMAX

ZPOPMAX 的阻塞版本。

语法:BZPOPMAX key [key ...] timeout

  • key: 要操作的有序集合的键名。
  • timeout: 如果所有指定的有序集合都为空,客户端将阻塞等待的最长时间(以秒为单位)。超时时间为0表示一直阻塞直到有数据可用,如果设置为正数,则表示等待的最长时间为该秒数。

8. ZPOPMIN与ZBPOPMIN

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

ZBPOPMIN,ZPOPMIN的阻塞版本

9. ZRANK与ZRERANK

ZRANK 命令用于获取有序集合中指定成员的排名,排名从 0 开始计数(即第一名为 0,第二名为 1,依此类推)。

语法:ZRANK key member

  • key: 要操作的有序集合的键名。
  • member: 要获取排名的成员。

返回值

  • 如果成员存在于有序集合中,返回成员的排名(从 0 开始)。
  • 如果成员不存在于有序集合中,返回 nil

注意事项

  • ZRANK 是一个查询命令,用于获取有序集合中指定成员的排名。
  • 成员的排名是按照其分数从高到低的顺序进行排序的。
  • 如果有多个成员具有相同的分数,它们在排名中的位置将根据其在有序集合中的存储顺序决定。
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZADD myzset 3 "three"
(integer) 1
redis> ZRANK myzset "three"
(integer) 2
redis> ZRANK myzset "four"
(nil)

10. ZSCORE

返回指定元素的分数。
语法: ZSCORE key member
返回值:分数。
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZSCORE myzset "one"
"1"

11. ZREM

语法:ZREM key member [member ...]   删除指定的元素。

  • key: 要操作的有序集合的键名。
  • member: 要移除的成员名。可以指定一个或多个成员。

12. ZREMRANGEBYRANK

按照排序,升序删除指定范围的元素,左闭右闭。

语法:ZREMRANGEBYRANK key start stop

  • key: 要操作的有序集合的键名。
  • start: 起始排名(从 0 开始)。
  • stop: 结束排名(从 0 开始)。

功能说明

  • ZREMRANGEBYRANK 命令用于根据指定的排名范围删除有序集合中的成员。排名范围包含起始和结束排名。
  • 如果指定的排名范围超出了有序集合的实际排名范围(比如超过最后一个成员的排名),Redis 会自动截断范围,不会报错
  • 返回值为被成功移除的成员数量。
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZADD myzset 3 "three"
(integer) 1
redis> ZREMRANGEBYRANK myzset 0 1
(integer) 2
redis> ZRANGE myzset 0 -1 WITHSCORES
1) "three"
2) "3"
13. ZINCRBY
语法:

ZINCRBY key increment member

  • key: 要操作的有序集合的键名。
  • increment: 增加的分数值,可以为负数,如果成员不存在则会自动创建并赋值。
  • member: 要增加分数的成员。

返回值

  • 执行命令成功后,返回成员增加后的新分数值(以字符串形式返回)。
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZINCRBY myzset 2 "one"
"3"
redis> ZRANGE myzset 0 -1 WITHSCORES
1) "two"
2) "2"
3) "one"
4) "3

1.2 集合间操作

1. ZINTERSTORE - 求交集并存储结果

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

  • 功能:计算多个有序集合的交集,并将结果存储在一个新的有序集合 destination 中。
  • 参数解释
    • destination:存储结果的目标有序集合的键名。
    • numkeys:参与计算交集的有序集合的数量。
    • key [key ...]:参与计算交集的有序集合的键名。
    • WEIGHTS weight [weight ...](可选):指定权重,用于计算交集时调整每个有序集合中成员的分数。
    • AGGREGATE SUM|MIN|MAX(可选):指定如何聚合多个有序集合中相同成员的分数,可以是 SUM(求和,默认)、MIN(取最小值)、MAX(取最大值)。

2. ZUNIONSTORE - 求并集并存储结果

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

  • 功能:计算多个有序集合的并集,并将结果存储在一个新的有序集合 destination 中。
  • 参数解释
    • destination:存储结果的目标有序集合的键名。
    • numkeys:参与计算并集的有序集合的数量。
    • key [key ...]:参与计算并集的有序集合的键名。
    • WEIGHTS weight [weight ...](可选):指定权重,用于计算并集时调整每个有序集合中成员的分数。
    • AGGREGATE SUM|MIN|MAX(可选):指定如何聚合多个有序集合中相同成员的分数,可以是 SUM(求和,默认)、MIN(取最小值)、MAX(取最大值)。

3. ZDIFFSTORE - 求差集并存储结果

ZDIFFSTORE destination key [key ...]

  • 功能:计算第一个有序集合与其余有序集合的差集,并将结果存储在一个新的有序集合 destination 中。
  • 参数解释
    • destination:存储结果的目标有序集合的键名。
    • key [key ...]:参与计算差集的有序集合的键名。

2. 内部编码

Redis 通过对有序集合的元素数量和元素成员大小进行动态优化来选择不同的内部编码方式:

3.1 ziplist

当有序集合满足以下条件时,Redis 使用 ziplist(压缩列表)作为内部编码:

  • 有序集合包含的成员数量少于 ZSET_MAX_ZIPLIST_ENTRIES(默认为 128)。
  • 每个成员的长度(包括成员名和分数的存储开销)小于 ZSET_MAX_ZIPLIST_VALUE(默认为 64 字节)。

ziplist 是 Redis 的一种紧凑的连续内存结构,适合存储小型数据集。它可以在不引入额外指针和复杂结构的情况下实现快速的内存分配和访问。

3.2 skiplist

一旦有序集合的大小超过了 ziplist 的限制,Redis 将使用 skiplist 作为内部编码方式。skiplist 提供了更高效的插入、删除和范围查找操作,尤其是在处理大型数据集时表现更加优越。

1)当元素个数较少且每个元素较⼩时,内部编码为 ziplist:
127.0.0.1:6379> zadd zsetkey 50 e1 60 e2 30 e3
(integer) 3
127.0.0.1:6379> object encoding zsetkey
"ziplist"
2)当元素个数超过 128 个,内部编码 skiplist:
127.0.0.1:6379> zadd zsetkey 50 e1 60 e2 30 e3 ... 省略 ... 82 e129
(integer) 129
127.0.0.1:6379> object encoding zsetkey
"skiplist"
3)当某个元素⼤于 64 字节时,内部编码 skiplist:
127.0.0.1:6379> zadd zsetkey 50 "one string bigger than 64 bytes ... 省略 ..."
(integer) 1
127.0.0.1:6379> object encoding zsetkey
"skiplist"

3. 使用场景

3.1. 排行榜和计分系统

有序集合最典型的使用场景之一是排行榜和计分系统。通过有序集合的分数(score)和成员(member)的结合,可以轻松实现各种排名功能:

  • 实时排行榜:将用户按照分数高低排名,比如游戏中的积分排行榜或网站中的用户活跃度排行榜。

  • 热门内容:根据某个指标(如点赞数、浏览量)将内容(文章、视频等)进行排行,展示热门和流行的内容。

  • 计分系统:记录用户的行为得分,比如用户在应用中的交互行为,通过增减分数来评估用户活跃度和贡献度。

场景复现:

比如我们需要展示博客系统中的用户发布的博客的点赞热门:

假设有以下几个用户及其发布的博客的点赞数据:

  • 用户ID "user1:article:1" 点赞数 1000
  • 用户ID "user2:article:1" 点赞数 800
  • 用户ID "user3:article:1" 点赞数 1200
  • 用户ID "user4:article:1" 点赞数 950

使用 ZADD 命令向有序集合中添加用户博客的点赞数据:

# 向有序集合中添加用户博客的点赞数据
ZADD blog_likes 1000 "user1:article:1"
ZADD blog_likes 800 "user2:article:1"
ZADD blog_likes 1200 "user3:article:1"
ZADD blog_likes 950 "user4:article:1"

更新点赞数据

当用户点赞或取消点赞时,我们需要更新有序集合中的点赞数据。假设用户 "user2" 获得了额外的 200 个点赞:

# 用户 "user2" 获得了额外的 200 个点赞
ZINCRBY blog_likes 200 "user2:article:1"

再次查看点赞热榜

更新后,再次查看点赞热榜的前 3 名:

ZREVRANGE blog_likes 0 2 WITHSCORES

1) "user3:article:1"
2) "1200"
3) "user2:article:1"
4) "1000"
5) "user1:article:1"
6) "1000"

2. 社交网络中的关注关系

在社交网络中,有序集合可以用来存储用户的关注关系和粉丝列表:

  • 关注关系:每个用户对应一个有序集合,集合中的成员是其关注的用户,分数可以是关注时间或其他衡量关系密度的指标。

  • 粉丝列表:反向查询,通过用户的 ID 查找关注该用户的其他用户列表,也可以通过分数范围查询粉丝的关注度。

3. 渐进式遍历

渐进式遍历是一种逐步处理大量数据的方法,适用于需要在有限时间和资源内处理大数据集的场景。在 Redis 中,渐进式遍历主要用于有序集合(ZSET)和其他数据结构的扫描和遍历操作,通过分批次逐步处理数据来避免阻塞和性能下降

为什么需要渐进式遍历

在处理大数据集时,直接遍历整个数据集可能会导致以下问题:

  1. 阻塞:一次性处理大量数据会导致服务器长时间阻塞,影响其他操作的执行。
  2. 内存消耗:大数据集的遍历可能会占用大量内存,导致内存溢出或性能下降。
  3. 响应时间:对用户来说,长时间的操作响应可能会带来不好的用户体验。

渐进式遍历通过将大数据集的处理分解为多个小批次,逐步进行,能够有效缓解上述问题。

使用 ZSCAN 进行渐进式遍历

ZSCAN 命令是 Redis 提供的用于有序集合(ZSET)的渐进式遍历工具。它允许在不阻塞服务器的情况下,逐步扫描有序集合中的元素。

基本用法

ZSCAN 的基本语法如下:

ZSCAN key cursor [MATCH pattern] [COUNT count]

  • key:要遍历的有序集合的键。
  • cursor:游标,初始值为 0,每次调用 ZSCAN 都会返回一个新的游标,直到游标再次变为 0,表示遍历结束。
  • MATCH pattern:匹配模式,可选,用于筛选出符合特定模式的元素。
  • COUNT count:每次返回的元素个数提示,实际返回数量可能会大于或小于这个值。

假设我们有一个有序集合 blog_likes,其中存储了用户发布的博客的点赞数据。我们希望逐步遍历这个有序集合中的所有元素。

首先,向有序集合中添加一些数据:

ZADD blog_likes 1000 "user1:article:1"
ZADD blog_likes 800 "user2:article:1"
ZADD blog_likes 1200 "user3:article:1"
ZADD blog_likes 950 "user4:article:1"

使用 ZSCAN 命令逐步遍历这个有序集合:

# 第一次扫描,从游标 0 开始
ZSCAN blog_likes 0

# 返回结果示例:
1) "4"
2) 1) "user1:article:1"
   2) "1000"
   3) "user3:article:1"
   4) "1200"

# 使用新的游标继续扫描
ZSCAN blog_likes 4

# 返回结果示例:
1) "0"
2) 1) "user2:article:1"
   2) "800"
   3) "user4:article:1"
   4) "950"

每次调用 ZSCAN 都会返回一个新的游标和一些元素,直到游标再次变为 0,表示遍历结束。

注意:

渐进性遍历 scan 虽然解决了阻塞的问题,但如果在遍历期间键有所变化(增加、修改、删除),可能导致遍历时键的重复遍历或者遗漏,这点务必在实际开发中考虑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1863138.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

减少液氮罐内液氮损耗的方法

监测与管理液氮容器的密封性能 液氮容器的密封性能直接影响液氮的损耗情况。一个常见的损耗源是容器本身的密封不良或老化导致的泄漏。为了有效减少液氮损耗,首先应当定期检查液氮容器的密封性能。这可以通过简单的方法如肉眼检查外观,或者更精确的方法…

SEO与AI的结合:如何用ChatGPT生成符合搜索引擎优化的内容

在当今数字时代,搜索引擎优化(SEO)已成为每个网站和内容创作者都必须掌握的一项技能。SEO的主要目标是通过优化内容,使其在搜索引擎结果页面(SERP)中排名更高,从而吸引更多的流量。然而&#xf…

嵌入式学习——硬件(ARM体系架构)——day51

1. S3C2440基础知识——一条指令四个字节 1.1 定义 S3C2440 是三星(Samsung)公司设计的一款基于 ARM920T 核心的微处理器,广泛应用于嵌入式系统中,属于三星的 S3C24xx 系列。 1.2 处理器核心 ARM920T:基于 ARM v5T …

[C#][opencvsharp]C#使用opencvsharp进行年龄和性别预测支持视频图片检测

使用 OpenCVSharp 来调用 age_net.caffemodel 和 gender_net.caffemodel 来进行性别和年龄预测涉及几个步骤。以下是一个简化的流程和示例文案: 1. 准备工作 确保你已经安装了 OpenCVSharp 和相关的依赖项。确保你有 age_net.prototxt、age_net.caffemodel、gende…

市面上很轻的 100kW 负载组

FX100S-C 负载组 EAK的 FX100S-C 负载组在轻质外壳中以 415Vac 50Hz 提供 100kW 的连续负载。数字仪表允许您测量功率、电压、电流和频率,同时还允许您在进行测试时记录数据。 EAK是市场上最轻的 100kW 负载组之一,它将使您能够访问其他负载组无法到达…

离线部署OpenIM

目录 1.提取相关安装包和镜像 2.安装docker和docker-compose 3.依次导入镜像 4.解压安装包 5.执行安装命令 6.PC Web 验证 7.开放端口 7.1IM 端口 7.2Chat 端口 7.3 PC Web 及管理后台前端资源端口 “如果您在解决类似问题时也遇到了困难,希望我的经验分享…

服务运营 | MS文章精选:线上点单,当真免排队?餐饮零售与医疗场景中的全渠道运营

编者按: 小A走进了一家奶茶店,准备向店员点单,但却在屏幕上看到还有98杯奶茶待制作(因为线上订单突然暴增)。因此,小A不满地嘟囔着离开了奶茶店。这个例子展示了线上渠道可能会对线下渠道造成一些负面影响…

并发编程-04synchronized原理

并发编程-04synchronized原理 一 synchronized基础 1.1 并发安全问题 在学习synchronized原理之前,我们先要了解synchronized是干嘛用的,什么场景下需要使用它,以及它的使用方式有哪些?接下来我们去根据一个业务场景去了解下sy…

【排序 队列】1585. 检查字符串是否可以通过排序子字符串得到另一个字符串

本文涉及知识点 排序 队列 LeetCode1585. 检查字符串是否可以通过排序子字符串得到另一个字符串 给你两个字符串 s 和 t ,请你通过若干次以下操作将字符串 s 转化成字符串 t : 选择 s 中一个 非空 子字符串并将它包含的字符就地 升序 排序。 比方说&a…

密码学:用随机函数隐藏指纹

英文中e的出现频率高,加密后,频率最高的那个符号代表e。这是历史上的一次真实案例。这些符号的概率,叫做“指纹”。 把e加密成2个符号,用随机函数选择,例如70%概率下选择符号1,30%选择符号2。解密时&#…

Pythonnet能导入clr,但无法引入System模块?

【pythonnet详解】—— Python 和 .NET 互操作的库_pythonnet 详细使用-CSDN博客 Python中动态调用C#的dll动态链接库中方法_python 如何调用c# dll-CSDN博客 需求&#xff1a;Python调用并传List<float>类型参数给.Net 起初&#xff1a;直接 # 创建一个Python浮点数…

数字逻辑--课程设计报告

##智力竞赛抢答器设计 如果对这个有兴趣或者需要电路图或者报告的话请私聊我

Linux 中变量的取用与设定

优质博文&#xff1a;IT-BLOG-CN Linux是一个多人多任务的环境&#xff0c;每个人登录系统都能取得一个bash shell&#xff0c;每个人都能够使用bash下达mail这个指令来接收自己的邮箱等等。问题是&#xff0c;bash如何得知你的邮箱是那个文件&#xff1f;这就需要『变量』的帮…

JavaWeb系列八: WEB 开发通信协议(HTTP协议)

HTTP协议 官方文档什么是HTTP协议快速入门页面请求的一个问题(分析)http请求包分析(get)http请求包分析(post)GET请求 POST请求分别有哪些http响应包分析常用的状态码说明状态码200状态码404状态码500状态码302状态码304 MIME类型MIME介绍常见的 MIME 类型 官方文档 HTTP常见请…

不会吧!KVM竟然不支持磁盘的精简置备!?

正文共&#xff1a;999 字 17 图&#xff0c;预估阅读时间&#xff1a;1 分钟 前面我们安装了KVM主机&#xff08;KVM部署初体验&#xff09;&#xff0c;接下来肯定是要简单操作一下&#xff0c;体验体验如何使用。 上次我们是在主机的桌面环境中打开的“虚拟系统管理器VMM”&…

192.回溯算法:电话号码的字母组合(力扣)

代码解决 class Solution { public:// 定义每个数字对应的字母映射const string letterMap[10] {"", // 0"", // 1"abc", // 2"def", // 3"ghi", // 4"jkl", // 5"mno", // 6"pqrs&…

可以给任意软件exe一键加验证加卡密的免费工具!

目录 引言TProtect网络验证工具简介主要特性一键快速接入多平台支持高度安全灵活的用户和卡密设置自动更新与提示代理端支持高级模式防止多开机制 使用方法步骤一&#xff1a;获取TProtect工具步骤二&#xff1a;打开服务器步骤三&#xff1a;添加要加密的软件步骤四&#xff1…

关于Pycharm右下角不显示解释器interpreter的问题解决

关于Pycharm右下角不显示解释器interpreter的问题 在安装新的Pycharm后&#xff0c;发现右下角的 interpreter 的选型消失了&#xff1a; 觉得还挺不习惯的&#xff0c;于是网上找解决办法&#xff0c;无果。 自己摸索了一番后&#xff0c;发现解决办法如下&#xff1a; 勾…

科普文:贝叶斯过滤器判定垃圾邮件

简介 贝叶斯分类的运作是借着使用标记(一般是字词&#xff0c;有时候是其他)与垃圾邮件、非垃圾邮件的关连&#xff0c;然后搭配贝叶斯推断来计算一封邮件为垃圾邮件的可能性。 贝叶斯垃圾邮件过滤是非常有威力的技术&#xff0c;可以修改自己以符合个别使用者的需要&#xff0…

STM32HAL库--PWR低功耗实验(速记版)

电源控制&#xff08;PWR&#xff09;简介 电源控制部分&#xff08;PWR&#xff09;概述了不同电源域的电源架构以及电源配置控制器。PWR 的内容比较多&#xff0c;我们把它们的主要特性概括为以下 3 点&#xff1a; 电源系统&#xff1a;USB 稳压器、内核域(VCORE)、…