2024.1.6 关于 Redis 数据类型 Zset 常用命令

目录

Zset 基本概念

Zset 命令操作 

ZADD

ZRANGE

ZREVRANGE

ZCARD

ZCOUNT

ZRANGEBYSCORE

ZPOPMAX

BZPOPMAX 

ZPOPMIN

BZPOPMIN

ZRANK

ZREVRANK

ZSCORE

ZREM

ZREMRANGEBYRANK

ZREMRANGEBYSCORE

ZINCRBY


Zset 基本概念

  • Set(集合)
  1. 元素具有唯一性
  2. 元素顺序无关紧要

实例理解

  • Set 类型 [1,2,3] 和 [2,1,3] 为同一个集合

  • List (列表)
  1. 元素具有唯一性
  2. 元素具有有序性,强调元素顺序十分重要

实例理解

  • List 类型 [1,2,3] 和 [2,1,3] 为两个不同的列表

  • Zset(有序集合)
  1. 元素具有唯一性
  2. 元素具有有序性,强调的是 升序 或 降序

排序规则

  • Zset 中的 member 引入了 分数(score)浮点类型,形如(member - score)
  • 即每个 member 都会安排一个分数(score),并按照各自 score 的大小进行 升序排序
  • 我们通常将(member - score)称为一个 pair

实例理解

注意:

  • Zset 中的 元素(member) 具有唯一性,但 分数(score)可重复
  • Zset 的主要作用为存储 元素(member)
  • 即分数(score)仅作为 元素(member)在 有序集合 Zset 中排序位次的参考依据

表格总结

数据结构是否允许重复元素是否有序有序依据应用场景
列表索引下标时间轴、消息队列
集合标签、社交
有序集合分数排行榜系统

Zset 命令操作 

ZADD

  • 用于 向 zset 中添加 元素(member)和 分数(score)

注意:

  • 不要把 member 和 score 理解成 "键值对" ,即(key - value)
  • 键值对 具有明确的 角色区分,即 谁是键 谁是值 是已经明确好了的,一定是根据 键(key) 来查到 值(value)
  • 而对于有序集合来说,既可以通过 member 找到对应的 score 又可以通过 score 找到相匹配的 member

语法:

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

[NX | XX] 

  • XX:只更新已存在元素 ,不添加新元素
  • NX:只添加新元素,不更新已存在元素

[GT | LT]

  • LT:只更新已存在元素,且当 新设置的分数 小于 旧分数 时才会更新,不阻止添加新元素
  • GT:表示只更新存在的元素,且当 新设置的分数 大于 旧分数 时才会更新,不阻止添加新元素

[CH]

  • 描述了 zadd 命令的返回值
  • 默认 zadd 命令返回 新增元素 的个数
  • 当添加 CH 选项后,zadd 命令返回 新增元素 + 修改元素 的个数

[INCR]

  • 添加该选项,zadd 命令将如同 zincrby 命令
  • 添加该选项后,此时的 zadd 命令只能指定一对(element - score)

时间复杂度:

  • 对于添加的每一项来说,其时间复杂度均为 O(logN)
  • N 为 有序集合 中的元素个数

注意:

  • 由于 zset 采用了 跳表 作为其内部数据结构
  • 新增元素时按照元素自身的分数插入到相应位置
  • 这样的设计使得在进行插入操作时,充分利用了跳表的有序性
  • 因而将时间复杂度优化为 O(logN)  而不是 O(N)

重点理解:

  • 如果多个元素具有相同的分数,此时便会按照字典序进行排列
  • 当然按分数排列仍让是放在首位的

ZRANGE

  • 用于返回指定区间里的元素,按照分数升序遍历

语法:

zrange key start stop [withscores]
  • 类似于 lrange 可以指定一对下标构成的区间,即 [start,stop] 区间
  • 添加 withscores 选项,可以在返回时把分数也带上

注意:

  • 有序集合 本身元素就是有先后顺序的 谁在前 谁在后,都是很明确的!
  • 因此也就可以给这个有序集合赋予 下标 这样的概念了

时间复杂度:

  • O(logN + M)
  • 先根据 start 下标找到边界元素,再进行遍历操作
  • N 为 有序集合 中的元素个数
  • M 为下标 start 到 stop 之间的元素个数 

实例理解

  • 我们利用 zrange 命令,来结合理解 zadd 命令

  • 此处我们利用 zadd 命令向有序集合中添加若干 pair

  • Redis 内部存储数据时,是按照二进制的方式来进行存储的
  • 这就意味着 Redis 服务器并不负责 字符的编码 
  • 所以要把二进制字节对应回汉字,需利用客户端来提供支持
  • 我们在启动 Redis 客户端时,添加上后缀 "--raw" 即可

  • 此处我们利用 zadd 命令来修改指定 元素 的 分数

  • 修改完分数后,还需对该元素进行重新排序,以此来维持 有序序列 的 升序顺序

  • 关于 zadd 命令选项 [NX | XX] 

  • 关于 zadd 命令选项 [CH]

  • 关于 zadd 命令选项 [INCR]


ZREVRANGE

  • 用于返回指定区间里的元素,按照分数降序进行遍历
  • reverse ——> 逆序

语法:

zrevrange key start stop [withscores]

时间复杂度:

  • O(logN + M)
  • N 为 有序集合 中的元素个数
  • M 为下标 start 到 stop 之间的元素个数 

实例理解

  • 此处的区间,两个参数的顺序是无需变换!

ZCARD

  • 用于获取指定 zset 的元素个数

语法:

zcard key

时间复杂度:

  • O(1)

返回值:

  • 指定 zset 中的元素个数

实例理解


ZCOUNT

  • 用于 返回分数在 min 和 max 之间的元素个数

 语法:

zcount key min max 
  • 默认为 闭区间,即 [min,max]
  • 如果想排除边界值,可以加上括号 "("

补充:

  • min 和 max 可以写成 浮点数,因为 zset 的分数(score)本身就是浮点数 
  • 在浮点数中存在两个特殊的数值
  1. inf:无穷大(+∞)
  2. -inf:负无穷大(-∞)
  • zcount 中分数也是支持使用 inf 和 -inf 作为 max 和 min 的!

注意:

  • 此处的 负无穷大 不是指的无穷小!
  • 无穷小是无限趋近于 0 的数值,而 负无穷大 的绝对值 等于 无穷大

时间复杂度:

  • O(logN)

返回值:

  • 满足条件的元素个数

重点理解:

  • zcount 指定 分数区间 [min,max]
  • 先根据 min 找到对应的元素,再根据 max 找到对应的元素,时间复杂度为 O(logN)

问题:

  • 如果再进行一个遍历,是不是就知道 [min,max] 区间里的元素个数了呢?
  • 那么此时的时间复杂度将为 O(M + logN)
  • 其中 M 为区间中元素个数,N 为整个有序集合的元素个数

回答:

  • 实际上 zset 内部会记录每个元素当前的 次序
  • 查询到元素,便可以直接知道该元素所在的次序
  • 直接利用 max 对应的元素次序 和 min 对应的元素次序 相减 再 +1
  • 由此我们便可以 O(1) 的代价知道 min 和 max 之间的元素个数
  • 并非是通过遍历的方式!!
  • 所以此处 zcount 命令的时间复杂度为 O(logN)

实例理解

注意:

  • 此处 排除边界值 的表示比较奇葩,需重点注意!

ZRANGEBYSCORE

  • 用来 返回指定分数区间里的元素
  • 与 zcount 命令相似,只不过 zcount 返回的是 指定分数区间的元素个数
zrangebyscore key min max [withscores]

时间复杂度:

  • O(M + logN)
  • N 为 有序集合 中的元素个数
  • M 为分数 min 到 max 之间的元素个数 

实例理解

注意:

  • 该命令在 6.2.0 之后废弃,且该命令功能被合并到 zrange 命令中

ZPOPMAX

  • 用于 删除并返回分数最高的 count 个元素

语法:

zpopmax key [count]

时间复杂度:

  • O(M * logN)
  • N 为 有序集合 中的元素个数
  • M 为 count 值,即要删除的元素个数

返回值:

  • 被删除的元素(包括 member 和 score)

重点理解:

  • zpopmax 命令删除的是有序集合的最大值,其最大值就相当于末尾元素,也就相当于 尾删

问题一:

  • 既然是尾删,为什么不把末尾元素的特殊位置给记录下来?
  • 后续如果需要删除的话,其时间复杂度不就可以为 O(1) 了嘛?还省去了查找的过程!
  • O(logN) ——> O(1)

回答:

  • 这个事是有可能的!
  • 但是很遗憾,Redis 并没有这么做
  • 事实上,Redis 的源码中,针对有序集合,确实是记录了 尾部 这样的特殊位置
  • 但是实际删除的时候,并没有用到这个特性,而是直接调用了一个 通用的删除函数,即给定一个 member 的值,进行查找到位置之后再删除
  • 此处我认为是存在优化空间的!

问题二:

  • 虽然存在这样的优化空间,但是未来会真的优化吗?

回答:

  • 也不好说
  • 优化这种活,要优化到刀刃上!
  • 优化一般是要先找到性能瓶颈,再针对性能优化!
  • 因为当前的这个 O(logN) 的速度其实是不慢的!
  • 如果 N 不是非常夸张的大,基本是可以近似看作O(1)的

实例理解

  • 此处类似于 top K 问题

  • 如果存在多个元素分数相同,且同时为最大元素时zpopmax 命令仍然只删除其中的一个元素!
  • 虽然分数是主要因素,但如果分数相同仍会按照 member 字符串的字典序决定先后!


BZPOPMAX 

  • ZPOPMAX 命令的阻塞版本

注意:

  • blist 和 brpop 这两个命令是针对 List ,实现类似于阻塞队列的效果
  • 咱们这里的 有序集合 也可以视为是一个优先级队列 
  • 有时候 也需要一个带有 阻塞功能 的优先级队列

语法:

bzpopmax key [key ...] timeout 
  • 每个 key 均对应一个 有序集合
  • 阻塞也是在 有序集合 为空的时候触发阻塞,阻塞到有其他客户端插入元素 为止
  • timeout 代表超时时间,即最多阻塞多久,单位为 秒 且支持小数形式

时间复杂度:

  • O(logN)

返回值:

  • 被删除的元素(包括 member 和 score)

问题:

  • 如果当前 bzpopmax 命令同时监听了多个 key,假设 key 是 M 个
  • 此时 时间复杂度是 O(M * logN) 吗?

回答:

  • 不是!
  • 啥时候才需要 * M ?
  • 即每个这样的 key 上面都删除一次最大元素!
  • 而 当 zpopmax 命令同时监听多个 key 时,哪个 key 对应的有序集合最快插入元素,便删除该 key 对应有序集合的最大值! 

实例理解

  • 当然 如果有序集合中已经有了元素,直接就能返回!不会进行阻塞了!

ZPOPMIN

  • 用于 删除并返回分数最低的 count 个 元素

语法:

zpopmin key [count]

时间复杂度:

  • O(M * logN)
  • N 为 有序集合 中的元素个数
  • M 为 count 值,即要删除的元素个数

返回值:

  • 被删除的元素(包括 member 和 score)

注意:

  • zpopmin 和 zpopmax 命令的逻辑是一致的,即均由同一个函数实现
  • 虽然 Redis 的有序集合记录了开头的位置,但是删除的时候使用的是通用的删除函数

    导致出现了重新查找的过程

返回值:

  • 被删除的元素(包括 member 和 score)

实例理解


BZPOPMIN

  • ZPOPMIN 命令的阻塞版本

语法:

bzpopmin key [key ...] timeout
  • 用法和 bzpopmax 命令一样

时间复杂度:

  • O(logN)

返回值:

  • 被删除的元素(包括 member 和 score)

实例理解


ZRANK

  • 用于返回指定元素的下标,升序

注意:

  • zrank 命令得到的下标是从前往后算的,即升序

语法:

zrank key member

时间复杂度:

  • O(logN)
  • 最主要是有一个查询位置的过程

返回值:

  • 元素(member) 对应的下标

实例理解


ZREVRANK

  • 用于返回指定元素的下标,降序
  • rev ——> reverse

注意:

  • zrevrank 命令得到的下标是从后往钱算的,即降序

语法:

zrevrank key member

时间复杂度:

  • O(logN)

返回值:

  • 元素(member) 对应的下标

实例理解


ZSCORE

  • 用于查询指定元素的分数

语法:

zscore key member

时间复杂度:

  • O(1)

重点理解:

  • 上述介绍的命令,根据 member 查找元素,其时间复杂度均为 O(logN)
  • 但是此处 Redis 对 zscore 命令这样的查询操作做了特殊优化
  • 即付出额外的空间代价,但将时间复杂度优化到了 O(1)

返回值:

  • 指定元素所对应的分数

实例理解


ZREM

  • 用于 删除指定的元素

语法:

zrem key member [member ...]

时间复杂度:

  • O(M * logN)
  • N 为整个有序集合中元素个数
  • M 为 member 的个数
  • 因为此处的 member 不会有太多,也可认为是 O(logN)

返回值:

  • 本次操作成功删除的元素个数

实例理解


ZREMRANGEBYRANK

  • 用于删除指定下标范围的元素

语法:

zremrangebyrank key start stop
  • 使用这个下标描述的范围进行删除,且范围为 [start,stop]

时间复杂度:

  • O(M + logN)
  • N 为有序集合中的元素个数
  • M 为 [start,stop] 区间的元素个数

注意:

  • 此处查找位置,只需要进行一次,无需重复进行

返回值:

  • 删除成功的元素个数

实例理解


ZREMRANGEBYSCORE

  • 用于删除指定分数范围区间的元素

语法:

zremrangebyscore key min max
  • 使用这个分数描述的范围进行删除,且范围为 [min,max]

时间复杂度:

  • O(M + logN)
  • N 为有序集合中的元素个数
  • M 为 [min,max] 区间中元素个数

返回值:

  • 删除成功的元素个数

实例理解


ZINCRBY

  • 用于 为指定元素的关联分数添加指定的分数值

注意:

  • zincrby 命令不仅会修改分数内容,也会同时移动元素,来保持整个有序集合仍为升序

语法:

zincrby key increment member

时间复杂度:

  • O(logN)

返回值:

  • 增加后元素的分数

实例理解

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ARM笔记-----输入捕获

输入捕获可以对输入的信号的上升沿、下降沿或者双边沿进行捕获,常用的有测量输入信号的脉 宽,和测量 PWM 输入信号的频率和占空比这两种。 输入捕获的大概的原理 当捕获到信号的跳变沿的时候,把计数器 CNT 的值锁存到捕获寄 存器 CCR 中…

各种基础环境搭建

1、Python解释器安装 验证环境变量是否添加成功 winr --> cmd 输入python 会出现的问题 在命令行输入python弹出应用商城 是由于商城的环境变量在python的环境变量前面,移动到最下面就好 C:\Users…\AppData\Local\Microsoft*WindowsApps*

3d全景怎么拍摄?应用领域有哪些?

3d全景技术是综合了VR技术和全景拍摄的一种新型应用技术,通过3D全景技术可以为用户带来720度无死角的观看方式和真实的观看体验,那么3d全景是怎么拍摄制作的呢?应用领域又有哪些呢? 3d全景拍摄制作流程其实不难,常见的…

Linux-文件系统管理实验2

1、将bin目录下的所有文件列表放到bin.txt文档中,并将一共有多少个命令的结果信息保存到该文件的最后一行。统计出文件中以b开头的所有命令有多少个,并将这些命令保存到b.txt文档中。将文档中以p结尾的所有命令保存到p.txt文件中,并统计有多少…

多租户看这一篇就够了

什么是多租户?举个例子:马云、马化腾和刘强东三个人去租房子,他们因为家里经济困难所以勤工俭学,三个人决定合租一套三室一厅的房子,虽然每个人有自己的房间,但是家里的水电、厨房、卫生间和热水器都是大家…

攀登者1 - 华为OD统一考试

OD统一考试 分值: 100分 题解: Java / Python / C++ 题目描述 攀登者喜欢寻找各种地图,并且尝试攀登到最高的山峰。 地图表示为一维数组,数组的索引代表水平位置,数组的元素代表相对海拔高度。其中数组元素0代表地面。 例如:[0,1,2,4,3,1,0,0,1,2,3,1,2,1,0],代表如下…

2、Excel:基础概念、表格结构与常见函数

数据来源:八月成交数据 数据初探 业务背景 数据来源行业:金融行业(根据应收利息和逾期金额字段来判断) 可以猜测: 业务主体:某互联网金融公司(类似支付宝)也业务模式:给…

汽车电子行业的 C 语言编程标准

前言 之前分享了一些编程规范相关的文章,有位读者提到了汽车电子行业的MISRA C标准,说这个很不错。 本次给大家找来了一篇汽车电子行业的MISRA C标准的文章一同学习下。 什么是MISRA? MISRA (The Motor Industry Software Reliability Ass…

K8S-应用部署

1 应用管理解读 2 应用部署实践 资源对象管理关系 资源对象管理实践 手工方式: kubectl run pod名称 --imageimage地址资源清单方式: apiVersion: v1 kind: Pod metadata:labels:run: my-podname: my-pod spec:containers:- image: kubernetes-register.sswang.co…

报错curl: (6) Could not resolve host: raw.githubusercontent...的解决办法

我起初想要在macOS系统安装pip包,首先在终端安装homebrew,敲了命令:/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent...)" 之后触发的报错,报错内容:curl: (6) Could not resolve host: raw.…

1870_使用flx来增强counsel-M-x的模糊匹配功能

Grey 全部学习内容汇总: https://github.com/GreyZhang/editors_skills 1870_使用flx来增强counsel-M-x的模糊匹配功能 这一次算是趁热打铁,把之前优化掉了的counsel-M-x的匹配功能再推进一步。虽然还是没有达到spacemacs中的乱序匹配效果&#xff0c…

性能分析与调优: Linux 监测工具的数据来源

目录 一、实验 1.环境 2. proc目录 3. sys目录 4.netlink 5.tracepoint 6.kprobes 7. uprobes 二、问题 1.systemd如何查看启动时间 2.CentOS与Ubuntu如何安装bpftrace 3.snap有哪些常用的命令 4.snap如何安装store 5.如何列出使用bpftracede的OpenJDK USDT探针 …

私有仓库Gogs搭建(docker环境)

文章目录 环境准备Gogs简介MYSQL(docker) 搭建gogs(docker) 部署gogs初始化配置配置管理员信息仓库创建项目代码上传仓库 环境准备 本地环境安装git,参考Git分布式版本控制工具学习管理面板1panel,安装参考Armbian安装1panel教程服务器docker环境(如果使…

信号与槽机制

1. 信号与槽机制(重点,但不是难点) 1.1 机制: 是一种两个对象之间的通信的机制 例如: 鼠标双击-------文件夹图标---------打开文件夹功能 通信的过程: 用户对象 文件夹图标对象 鼠标双击,相当于…

OpenVINS学习6——VioManagerHelper.cpp,VioManagerOptions.h学习与注释

前言 VioManager类里还有VioManagerHelper.cpp,VioManagerOptions.h这两个文件&#xff0c;也包含了一些函数&#xff0c;这次接着看这个 。 整体分析 void VioManager::initialize_with_gt(Eigen::Matrix<double, 17, 1> imustate) 给一个状态&#xff0c;然后初始化…

基于YOLOv3开发构建道路交通场景下CCTSDB2021交通标识检测识别系统

交通标志检测是交通标志识别系统中的一项重要任务。与其他国家的交通标志相比&#xff0c;中国的交通标志有其独特的特点。卷积神经网络&#xff08;CNN&#xff09;在计算机视觉任务中取得了突破性进展&#xff0c;在交通标志分类方面取得了巨大的成功。CCTSDB 数据集是由长沙…

【Java】设计模式之两阶段终止

两阶段终止 两阶段终止&#xff0c;即Two Phase Termination。是用来终止线程的套路。 它的思想是&#xff0c;如何在一个线程T1中优雅地终止线程T2&#xff1f;这里的【优雅】指的是给T2一个料理后事的机会。 错误思路&#xff1a; 使用stop方法。stop 方法会真正杀死线程…

SpringMVC的工作流程

SpringMVC的工作流程图 SpringMVC的工作流程 1. 用户通过客户端向服务器发送请求&#xff0c;请求会被 SpringMVC的前端控制器DispatcherServlet所拦截。 2. DispatcherServlet拦截到请求后&#xff0c;会调用HandlerMapping处理器映射器。 3. 处理器映射器根据请求URL找到具…

HNU-数据库系统-实验4-存储过程与事务处理

数据库系统 课程实验4存储过程与事务处理 计科210X 甘晴void 202108010XXX 目录 文章目录 数据库系统 课程实验4<br>存储过程与事务处理实验目的实验环境实验准备表设计初始数据 实验内容4.1 存储过程实验实验内容与要求实验重点和难点实验过程&#xff08;0&#xff0…

八大算法排序@堆排序(C语言版本)

目录 堆排序大堆排序概念算法思想建堆建堆核心算法建堆的代码 排序代码实现 小堆排序代码实现时间复杂度空间复杂度 特性总结 堆排序 堆排序借用的是堆的特性来实现排序功能的。大堆需要满足父节点大于子节点&#xff0c;因此堆顶是整个数组中的最大元素。小堆则相反&#xff0…
最新文章