六、Redis五种常用数据结构-zset

news2024/11/26 2:30:10

zsetRedis的有序集合数据类型,但是其和set一样是不能重复的。但是相比于set其又是有序的。set的每个数据都有一个double类型的分数,zset正是根据这个分数来进行数据间的排序从小到大。有序集合中的元素是唯一的,但是分数(score)是可以重复的。每个zset集合最多可以存放232-1个数据。zset常被用于排行榜功能。

1、常用命令

  • zadd key score1 member1 [score2 member2]:向有序集合中添加一个或多个数据,或者更新已存在成员的分数(member会先删除在重新插入)。
  • zcard key:获取集合的数据个数。
  • zcount key min max:计算集合中在指定分数区间内的数据个数。
  • zincrby key increment member:在集合指定成员的分数加上增量increment。increment为负数表示减去相应的值。
  • zinterstore destination numberkeys key [key…]:计算给定的一个或者多个集合的交集,并将结果存储到destination中。结果集中某个成员的分数是所有给定的集合该成员所有分数的和。
  • zlexcount key min max:在有序集合中计算指定字典区间内的成员数量。
  • zrange key start end[withscores]:通过索引区间返回指定区间内的成员。
  • zrangebylex key min max[limit offset count]:通过字典区间返回有序集合的成员。
  • zrangebyscore key min max[withscores][limit]:通过分数返回集合中的成员。
  • zrank key member:返回有序集合中指定成员的索引。
  • zrem key member [memeber…]:删除集合中一个或者多个成员。
  • zremrangebylex key min max:移出集合中指定字典区间内的所有成员。
  • zremrangebyrank key start stop:移出有序集合中给定的排名区间内的所有成员。
  • zrevrange key start end[withscores]:返回指定索引区间内的成员,分数从高到低。
  • zrevrangebyscore key max min[withscores]:返回集合中指定分数区间内的成员,分数从高到低。
  • zrevrank key member:返回集合中指定成员的排名。0表示最高。
  • zscore key member:返回集合中指定成员的分数。
  • zunionstore destination numberkeys key [key…]:计算给定的一个或者多个集合的并集,并存储在destination中。
  • zscan key cursor[match pattern][COUNT count]:迭代集合的元素。

2、底层实现

zset的底层实现有两种,ziplistdict+skiplist

2.1、ziplist

2.1.1、使用条件
  1. 集合中元素数量小于128个。
  2. 每个元素的长度小于64字节。

以上两个条件有任何一个不满足,就会使用dict+skiplist的结构存储数据。
每个集合元素使用紧挨着的两个压缩列表节点保存,第一个节点保存元素的成员,第二个保存元素的分数。
image.png

2.1.2、ziplist结构

见Hash中的ziplist

2.2、dict+skiplist

2.2.1、介绍
  • dict用来存储valuescore的映射关系,这样就可以在O(1)时间内找到对应valuescore值。
  • skiplist按照从小到大的顺序存储分数。
  • skiplist每个元素的值都是[score,value]对。
2.2.2、zset结构
typedf struct zset{
	//字典,键为value,值为score
    dict* dict;
    //跳表,按分值进行排序
    zskiplist *zsl;
}zset;
typedf struct zskiplist{
	//头节点
    struct zskiplistNode *header;
    //尾节点
    struct zskiplistNode *tail;
    //跳表中的元素个数
    unsigned long length;
    //目前表内节点最高的层数
    int level;
}zskiplist;

zskiplist的示意图如下:
image.png

typedf struct zskiplistNode{
    //具体的数据
	sds ele;
    //分数
    double size;
    //后退指针
    struct zskiplistNode *backward;
    struct zskiplistLevel{
    	//前进指针
        struct zskiplistNode *forward;
        /跨服
        unsigned int span;
    }level[]; //层数数组  最大32
}zskiplistNode;

skiplistNode的示意图如下:
image.png

2.2.3、skiplist-跳表

跳表skiplistRedis中的使用场景只有一个,那就是作为zset的底层结构实现。跳表可以保证增、删、查的时间复杂度为O(logN),其余一般的链表结构的时间复杂度为O(n)相比,性能上有不少的提升。但是唯一美中不足的是跳表需要占用更多的空间,其实这就是一种空间换时间的思想。跳表的结构如下:
image.png
Redis中的跳表的实现有点类似于Kafka中的稀疏索引。
Kafka中进行持久化的时候,会生成两个文件,一个是xxxxxx.log,一个是xxxxxx.index,其中log文件中以链表的方式保存着消息。而index文件中则保存着这些消息的索引,或者说是偏移量,但又不是每一条消息的索引都在index文件中。index中的索引是稀疏的,比如log文件中的索引是0-10000,那么index文件中存储的索引可能是100,500,700,1000,5000,6500,每个索引中都保存着对应log文件中消息的具体位置。如图:
image.png
当要访问899这个索引的消息时,先去index文件中查找,找到了700到1000的这个区间,根据700这个索引去log文件中找到700这个索引的消息,然后顺着700这个消息顺序往下找,直到找到899这个索引的消息。从这个实现中,我们看到Kafka并没有对log文件进行全部的遍历,而是先通过index中的稀疏索引,找到一个大概的位置,然后顺序遍历。
image.png
Redis的跳表的实现方式与上面的类似,不过Kafka的稀疏索引只有一层,而Redis的稀疏索引是多层。如图:
image.png
所有的元素都会在L0层的链表中,根据分数进行排序,同时会有一部分节点被抽取到L1层,作为一个稀疏索引,同样L1层的索引也有一定的机会被抽取到L2层,以此类推,Redis允许跳表中一个节点最高有**64层,**一个跳表中最多存储264 个元素。

2.2.4、跳表-增、删、查

首先假定有这么一个跳表,这里只展示分数:
image.png
如果要查找分数为66的元素,首先在L2层的索引查找。很明显。66位于25和85之间:
image.png
然后根据获得的区间,去对应的L1的区间查找,得到一个更精确的区间:
image.png
最终根据更精确的区间,去L0层顺序遍历,即可找到要查找的元素:
image.png
上述即是对跳表原理的一个描述。
这种跳表的实现,其实和二分查找的思路接近,只是一方面因为二分查找法只能适用与数组,而无法用于链表,所以为了让链表有二分查找类似的效率,就以空间换时间来达到目的。
跳表因为是一个根据分数权重进行排序的列表,可以在很多场景中使用,比如排行榜,搜索排序等。

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

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

相关文章

51单片机软件环境安装

keli5的安装 把CID放到破解程序中 破解程序会给一串数字然后填到那个框中 驱动程序的安装 安装完了以后 设备管理器会出现这个 同时c盘会出现这个文件夹

好题总结汇总

好题总结汇总 总结一些做完很有收获的题。 一、经典问题 DP的结合 1、题意: 给定 n n n 种颜色的球的数量 a 1 , a 2 , . . . , a n a_1, a_2, ..., a_n a1​,a2​,...,an​,选出一些不同种类的球(也就是在n种球中选球的任意情况),将球…

把项目打包成Maven Archetype(多模块项目脚手架)

1、示例项目 2、在pom.xml中添加archetype插件 <plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-archetype-plugin</artifactId><version>3.2.0</version> </plugin>3、打包排除某些目录 当我们使用…

上海AI Lab开源首个可替代GPT-4V的多模态大模型

与开源和闭源模型相比&#xff0c;InternVL 1.5 在 OCR、多模态、数学和多轮对话等 18 个基准测试中的 8 个中取得了最先进的结果。 上海AI Lab 推出的 InternVL 1.5 是一款开源的多模态大语言模型 (MLLM)&#xff0c;旨在弥合开源模型和专有商业模型在多模态理解方面的能力差距…

智慧公厕打造智慧城市新标杆

公共厕所作为城市基础设施的重要组成部分&#xff0c;直接关系到市民的生活品质和城市形象。传统的公厕管理方式存在着许多问题&#xff0c;如环境脏乱、清洁不及时等&#xff0c;给市民带来了诸多不便和不满。而智慧公厕作为一种全新的管理模式&#xff0c;通过物联网、大数据…

CSS-浮动

float (浮动) 作用&#xff1a;盒子的顶点是一样的&#xff0c;具备行内块的特征&#xff0c;能设置宽高 属性&#xff1a;float 属性值&#xff1a;left 浮动在网页左边 right 浮动在网页右边 .a{width: 100px;height: 100px;float:left;background-color: red;}.b…

AI算法-高数2-导数定义和公式

P14 2.1 导数的定义(一):2.1 导数的定义_哔哩哔哩_bilibili 导数定义&#xff1a; 导数公式&#xff1a; P15 2.1 导数的定义(二)&#xff1a;2.1 导数的定义&#xff08;二&#xff09;_哔哩哔哩_bilibili [a,b]可导&#xff0c;a的端点&#xff1a;右可导&#xff0c;b端点&…

[ 视频号]代替用户发布视频api

使用接口&#xff0c;替代用户使用设备直接发布视频api 接口地址&#xff1a; http://接口地址/api/v2 先调用登录接口&#xff0c;进行账号登录 登录二维码接口入参&#xff1a; {"appId": "","proxyIp": "","regionId"…

企业网站管理系统(多语言)源码搭建/部署/上线/运营/售后/更新

一款基于FastAdminThinkPHPUniapp开发的企业网站管理系统插件。支持自定义多语言、自定义模型与字段、自定义表单等功能。 功能特性 多语言功能&#xff08;默认中英文&#xff0c;后台可新增语言&#xff0c;并支持管理前台语言包&#xff09;有道api翻译功能响应式布局&…

安全加固

目录 1.文件锁定管理 2.设置用户账户有效期 3.查看并清除命令历史记录 4.设置用户超时登出时间 5.用户切换 6.用户提权 7.禁用重启热键CtrlAltDel 8.设置单用户模式密码 9.调整BIOS引导设置 10.禁止root用户从本地登录&#xff1a; 11.禁止root用户通过ss…

Linux系统编程--初识Linux

目录 一、相关概念 1、Unix系统 2、操作系统 操作系统的分类&#xff1a; 流行的操作系统&#xff1a; 3、Ubuntu系统及特点 二、Ubuntu安装 三、Linux目录 /根目录 路径分类&#xff1a; 四、shell指令 1、命令行提示符&#xff1a; 2、指令 2.1命令基本的操作&…

Meta FAIR: 深层网络不合理的低效性

这篇文章的标题"The Unreasonable Ineffectiveness of the Deeper Layers"巧妙地呼应了著名物理学家尤金维格纳在1960年发表的一篇论文"数学在自然科学中不合理的有效性"(The Unreasonable Effectiveness of Mathematics in the Natural Sciences)。维格纳…

ubuntu22.04服务器docker-compose方式部署ldap服务

一&#xff1a;系统版本 二&#xff1a;部署环境 节点名称 IP 部署组件及版本 配置文件路径 机器CPU 机器内存 机器存储 Ldap 10.10.10.111 self-service-password:latest phpldapadmin:latest openldap:latest openldap:/data/openldap/config phpldapadmin&#x…

梅兰日兰NSJ400N断路器NSJ400N可议价

梅兰日兰 NSJ400N 3 极 400 安培 600 伏交流电 紧凑型断路器 制造商的原始标签 脱扣单元&#xff1a;LS 功能 –&#xff08;长时间和短时间&#xff09; 负载侧凸耳 中断额定值&#xff1a;65kA 240 Vac 35kA 480 伏交流电压 18kA 600 伏交流电压 &#xff08;外观可能与照…

01、vue+openlayers6实现自定义测量功能(提供源码)

首先先封装一些openlayers的工具函数&#xff0c;如下所示&#xff1a; import VectorSource from ol/source/Vector; import VectorLayer from ol/layer/Vector; import Style from ol/style/Style; import Fill from ol/style/Fill; import Stroke from ol/style/Stroke; im…

【SpringBoot整合系列】SpringBoot整合RabbitMQ-消息过期(死信队列和延迟队列)

目录 业务场景传统轮询消息队列完整版 默认情况TTL&#xff08;消息的有效期&#xff09;TTL 的设置有两种不同的方式单条消息过期队列消息过期特殊情况 死信队列概述应用场景产生原因原理图死信交换机死信队列实现一下 延迟队列背景定时任务&#xff1f;延迟队列实现思路代码 …

Spring @Repository 注解

Spring 的项目严重依赖注解。 Repository 注解 在Spring2.0之前的版本中&#xff0c;Repository注解可以标记在任何的类上&#xff0c;用来表明该类是用来执行与数据库相关的操作(即dao对象)&#xff0c;并支持自动处理数据库操作产生的异常 在Spring2.5版本中&#xff0c;引…

校园网拨号上网环境下多开虚拟机,实现宿主机与虚拟机互通,并访问外部网络

校园网某些登录客户端只允许同一时间一台设备登录&#xff0c;因此必须使用NAT模式共享宿主机的真实IP&#xff0c;相当于访问外网时只使用宿主机IP&#xff0c;此方式通过虚拟网卡与物理网卡之间的数据转发实现访问外网及互通 经验证&#xff0c;将centos的物理地址与主机物理…

【概率论基础】 一篇文章缕清概率论常见概念关系

碎碎念&#xff1a;再写CSDN之前有一小段时间写数模公众号的经历&#xff0c;但是公众号看的人实在太少了&#xff0c;而且排版和公式、代码编辑都没有CSDN这么方便&#xff0c;所以坚持一算时间就没有更新了。公众号大多写的是概念性的基础&#xff0c;稍加修改搬到咱们的主战…

《二十二》Qt 音频编程实战---做一个音频播放器

1.UI界面制作 作为一个音乐播放器&#xff0c;最基础的肯定就是播放、暂停、上一首以及下一首&#xff0c;为了使这个界面好看一点&#xff0c;还加入了音量控制、进度条、歌曲列表等内容&#xff0c;至于这种配色和效果好不好看&#xff0c;我也不知道&#xff0c;个人审美一如…