Redis数据结构对象之集合对象和有序集合对象
集合对象
集合对象的编码可以是intset或者hashtable.
概述
intset编码的集合对象使用整数集合作为底层实现,集合对象包含的所有元素都被保存在整数集合里面。
另一方面,hashtable编码的集合对象使用字典作为底层实现,字典的每个键都是一个字符串对象,每个字符串对象包含了一个集合对象,而字典的值则全部被设置为NULL.
例子
- 举个例子。以下代码创建一个如图所示的intset编码集合对象
127.0.0.1:6379> SADD numbers 1 3 5
(integer) 3

- 举个例子,以下代码创建一个如图所示的hashtable编码集合对象
127.0.0.1:6379> SADD fruits "apple" "banana" "cherry"
(integer) 3

编码的转换。
当集合对象可以同时满足以下两个条件时,对象使用intset编码:
- 1.集合对象保存的所有元素都是整数值
- 2.集合对象保存的元素不超过512个
不能满足中两个条件的集合对象需要使用hashtable编码
对于使用intset编码的集合对象来说,当使用intset编码所需的两个条件的任意一个不能被满足时,就会执行对象的编码转换操作,原本保存在整数集合中的所有元素都会被转移并保存到字典里面,并且对象的编码也会从intset变为hashtable
注意:
第二个条件的上限值是可以修改的,具体请看配置文件中关于set-max-intset-entries选项的说明
例子
- 举个例子,以下代码创建了一个只包含整数的集合对象,该对象的编码为intset:
127.0.0.1:6379> SADD numbers 1 3 5
(integer) 3
不过,只要我们向这个只包含整数元素的集合对象添加一个字符串元素,集合对象的编码转移操作就会被执行:
127.0.0.1:6379> SADD numbers "seven"
(integer) 1
127.0.0.1:6379> OBJECT ENCODING numbers
"hashtable"
除此之外,如果我们创建一个包含512个整数元素的集合对象,那么对象的编码应该会是intset:
127.0.0.1:6379> EVAL "for i=1, 512 do redis.call('SADD', KEYS[1], i) end" 1 integers
(nil)
127.0.0.1:6379> SCARD integers
(integer) 512
但是我们再向集合添加一个新的元素,使得整个元素的元素数量变成513,那么对象的编码转换操作就会被执行:
127.0.0.1:6379> SADD integers 513
(integer) 1
127.0.0.1:6379> OBJECT ENCODING integers
"hashtable"
有序集合对象
有序集合的编码可以是ziplist或者skiplist。
概述
ziplist
ziplist编码的有序集合对象使用压缩列表作为底层实现,每个集合元素使用两个紧挨在一起的压缩列表节点来保存,第一个节点保存元素的成员(member),而第二个元素则保存元素的分值(score).压缩列表
内的集合元素按分值从小到大进行排序,分值较小的元素被放置在表头的位置(相对分值节点来说),而分值较大的元素则被放置在靠近表尾的位置。
例子
- 举个例子,如果执行以下ZADD命令,那么服务器将创建一个有序集合作为price键的值:
127.0.0.1:6379> ZADD price 8.5 apple 50 banana 6.0 cherry
(integer) 3
如果price键的值对象使用的是ziplist编码,那么这个值对象将会是如图所示的样子,对象使用的压缩列表则会是如图所示的样子


skiplist
skiplist编码的有序集合对象使用zset结构作为底层实现,,一个zset结构同时包含一个字典和一个跳跃表
typedef struct zset{zskiplist *zsl;dict * dict;
}zset
zset结构中的zsl跳跃表按分值从小到大保存了所有集合元素,每个跳跃表节点都保存了一个集合元素:
跳跃表节点的object属性保存了元素的成员,而跳跃表节点的score属性则保存了元素的分值。通过这个跳跃表,程序可以对有序集合进行范围型操作,比如ZRANK,ZRANGE等命令就是基于跳跃表API来实现的
除此之外,zset结构中的dict字典为有序集合创建了一个从成员到分值的映射,字典中的每个键值对都保存了一个集合元素:字典的键保存了元素的成员,而字典的值则保存了元素的分值。通过这个字典,程序可以用O(1)
复杂度查找给定成员的分值,ZSCORE命令就是根据这一特性实现的,而很多其他有序集合命令都在实现的内部用到了这一特性。
有序集合每个元素都是一个字符串对象,而每个元素的分值都是一个double类型的浮点数。值得一提的是,虽然zset结构同时使用跳跃表和字典来保存有序集合的元素,但这两种数据结构都会通过指针来共享相同的成员和分值,所以同时使用跳跃表和字典来保存集合元素不会产生任何重复成员或分值,也不会因此而浪费额外的内存
为什么有序集合需要同时使用跳跃表和字典来实现?
在理论上,有序集合可以单独使用字典或者跳跃表的其中一种数据结构来实现,但无论单独使用字典还是跳跃表,在性能上对比起同时使用字典和跳跃表都会有所降低。
- 举个例子,如果只是用字典来实现有序集合,虽然以O(1)的复杂度查找成员的分值这一特性会被保留,但是字典以无须的方式来保存集合元素,所以每次在执行范围型操作——比如ZRANK,ZRANGE等命令时,程序都需要对字典保存的所有元素进行排序,完成这种排序需要至少O(NlogN)时间复杂度,以及额外的O(N)内存空间(因为要创建一个数组来保存排序后的元素)。另一方面,如果只使用跳跃表来实现有序集合,那么跳跃表执行范围型操作的所有优点都会被保留,但因为没有了字典,所以根据成员查找分值这一操作的复杂度将从O(1)上升为O(logN)。因为以上原因,为了让有序集合的查找范围和范围型操作都尽可能快地执行,Redis选择了同时使用字典和跳跃表两种数据结构来实现有序集合
例子
举个例子,如果前面price键创建的不是ziplist编码的有序集合对象,而是skiplist编码的有序集合对象,那么这个有序集合对象将会如图所示,而对象所使用的zset结构也将如图所示


注意:
为了展示方便,在字典和跳跃表中重复展示了各个元素的成员和分值,但在实际中,字典和跳跃表会共享元素的成员和分值,所以并不会造成任何数据重复,也不会因此而浪费任何内存。
编码的转换
当有序集合对象可以同时满足以下两个条件时,对象使用ziplist编码
- 1.有序集合保存的元素数量小于128个
- 2.有序集合保存的所有元素成员的长度都小于64字节
不能满足以上两个条件的有序集合对象将使用skiplist编码
对于使用ziplist编码的有序集合对象来说,当使用ziplist比那吗所需的两个条件中的任意一个不能被满足时,程序就会执行编码转换操作,将原本储存在压缩列表里面的所有集合元素转移到zset里面,并将对象的编码从ziplist改为skiplist
例子
- 举个例子,以下代码展示了有序集合因为包含了过多元素而引发编码转换的情况:
// 对象包含了128个元素
127.0.0.1:6379> EVAL "for i=1, 128 do redis.call('ZADD', KEYS[1],i,i) end" 1 numbers
(nil)
127.0.0.1:6379> ZCARD numbers
(integer) 128
127.0.0.1:6379> OBJECT ENCODING numbers
"ziplist"
// 再添加一个新元素
127.0.0.1:6379> ZADD numbers 3.14 pi
(integer) 1
// 对象数量变为129个
127.0.0.1:6379> ZCARD numbers
(integer) 129
// 编码已改变
127.0.0.1:6379> OBJECT ENCODING numbers
"skiplist"
- 以下代码则展示了有序集合对象因为元素的成员过长而引起编码转换的情况
// 向有序集合添加一个成员只有三字节长的元素
127.0.0.1:6379> ZADD blah 1.0 www
(integer) 1
127.0.0.1:6379> OBJECT ENCODING blah
"ziplist"
// 向有序集合添加一个成员为66字节长的元素
ZADD blah 2.0 ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
// 编码已改变
127.0.0.1:6379> OBJECT ENCODING blah
"skiplist"
注意:
以上两个条件的上限值是可以修改的,具体请看配置文件中关于zset-max-ziplist-entries和zset-max-ziplist-value选项的说明
相关文章:
Redis数据结构对象之集合对象和有序集合对象
集合对象 集合对象的编码可以是intset或者hashtable. 概述 intset编码的集合对象使用整数集合作为底层实现,集合对象包含的所有元素都被保存在整数集合里面。 另一方面,hashtable编码的集合对象使用字典作为底层实现,字典的每个键都是一个…...
不要百花齐放
javascript中数组的遍历有如下方法: 1、for (var i 0; i < arr.length; i) 2、for(var item of arr) 3、for(var item in arr) 4、arr.forEach 5、arr.map 6、arr.filter 7、arr.find 8、arr.findIndex 9、arr.indexOf arr.lastIndexOf 10、arr.every…...
使用Java JDBC连接数据库
在Java应用程序中,与数据库交互是一个常见的任务。Java数据库连接(JDBC)是一种用于在Java应用程序和数据库之间建立连接并执行SQL查询的标准API。通过JDBC,您可以轻松地执行各种数据库操作,如插入、更新、删除和查询数…...
阿里云2核4G4M轻量应用服务器价格165元一年
阿里云优惠活动,2核4G4M轻量应用服务器价格165元一年,4Mbps带宽下载速度峰值可达512KB/秒,系统盘是60GB高效云盘,不限制月流量,2核2G3M带宽轻量服务器一年87元12个月,在阿里云CLUB中心查看 aliyun.club 当前…...
连续纯合片段(runs of homozygosity, ROH)的原理
连续纯合片段(Runs of Homozygosity, ROH)的原理及其结果查看方式包含以下几个方面: 原理 定义和识别: ROH是指基因组中由相同祖先遗传下来的连续纯合等位基因组成的片段。它们可以通过比较个体基因组上的等位基因序列来识别。当…...
UCORE 清华大学os实验 lab0 环境配置
打卡 lab 0 : 环境配置 : 首先在ubt 上的环境,可以用虚拟机或者直接在windows 上面配置 然后需要很多工具 如 qemu gdb cmake git 就是中间犯了错误,误以为下载的安装包,一直解压不掉,结果用gpt 检查 结…...
linux 安装常用软件
文件传输工具 sudo yum install –y lrzsz vim编辑器 sudo yum install -y vimDNS 查询 sudo yum install bind-utils用法可以参考文章 《掌握 DNS 查询技巧,dig 命令基本用法》 net-tools包 yum install net-tools -y简单用法: # 查看端口占用情况…...
OpenMP使用教程:入门到精通
在并行编程的领域中,OpenMP无疑是一个强大而又便捷的工具,它让程序员能够以最少的努力实现程序的并行化。本文将详细介绍OpenMP的基本概念、环境配置、核心指令以及实际代码示例,旨在帮助读者从入门到精通OpenMP的使用。 什么是OpenMP&#…...
华为组网:核心交换机旁挂防火墙,基于ACL重定向配置实验
如图所示,由于业务需要,用户有访问Internet的需求。 用户通过接入层交换机SwitchB和核心层交换机SwitchA以及接入网关Router与Internet进行通信。为了保证数据和网络的安全性,用户希望保证Internet到服务器全部流量的安全性,配置重…...
HarmonyOS NEXT应用开发—投票动效实现案例
介绍 本示例介绍使用绘制组件中的Polygon组件配合使用显式动画以及borderRadius实现投票pk组件。 效果预览图 使用说明 加载完成后会有一个胶囊块被切割成两个等大的图形来作为投票的两个选项,中间由PK两字分隔开点击左边选项,两个图形会随着选择人数…...
服务器端(Debian 12)配置jupyter与R 语言的融合
融合前: 服务器端Debian 12,域名:www.leyuxy.online 1.安装r-base #apt install r-base 2.进入R并安装IRkernel #R >install.packages(“IRkernel”) 3.通过jupyter notebook的Terminal执行: R >IRkernel::installspec() 报错 解决办…...
C语言---指针的两个运算符:点和箭头
目录 点(.)运算符箭头(->)运算符需要注意实际例子 C语言中的指针是一种特殊的变量,它存储了一个内存地址。点(.)和箭头(->)是用于访问结构体和联合体成员的运算符。…...
Linux 发布项目到OpenEuler虚拟机
后端:SpringBoot 前端:VUE3 操作系统:Linux 虚拟机:OpenEuler 发布项目是需要先关闭虚拟机上的防火墙 systemctl stop firewalld 一、运行后端项目到虚拟机 1、安装JDK软件包 查询Jdk是否已安装 dnf list installed | grep jd…...
相机与相机模型(针孔/鱼眼/全景相机)
0. 摘要 本文旨在较为直观地介绍相机成像背后的数学模型,主要的章节组织如下: 第1章用最简单的针孔投影模型为例讲解一个三维点是如何映射到图像中的一个像素 第2章介绍除了针孔投影模型外其他一些经典投影模型,旨在让读者建立不同投影模型…...
ARM32day4
1.思维导图 2.实现三个LED灯亮灭 .text .global _start _start: 使能GPIO外设时钟 LDR R0,0x50000A28 LDR R1,[R0]使能GPIOE ORR R1,R1,#(0X1<<4)使能GPIOF ORR R1,R1,#(0X1<<5) STR R1,[R0]设置引脚状态 LDR R0,0X50006000 LDR R1,[R0] 设置PE10为输出 BIC…...
从零开始写 Docker(六)---实现 mydocker run -v 支持数据卷挂载
本文为从零开始写 Docker 系列第六篇,实现类似 docker -v 的功能,通过挂载数据卷将容器中部分数据持久化到宿主机。 完整代码见:https://github.com/lixd/mydocker 欢迎 Star 推荐阅读以下文章对 docker 基本实现有一个大致认识: …...
网站引用图片但它域名被墙了或者它有防盗链,我们想引用但又不能显示,本文附详细的解决方案非常简单!
最好的办法就是直接读取图片文件,用到php中一个常用的函数file_get_contents(图片地址),意思是读取远程的一张图片,在输出就完事。非常简单~话不多说,直接上代码 <?php header("Content-type: image/jpeg&quo…...
Java八股文(RabbitMQ)
Java八股文のRabbitMQ RabbitMQ RabbitMQ RabbitMQ 是什么?它解决了哪些问题? RabbitMQ 是一个开源的消息代理中间件,用于在应用程序之间进行可靠的异步消息传递。 它解决了应用程序间解耦、消息传递、负载均衡、故障恢复等问题。 RabbitMQ …...
科研学习|论文解读——一种用于短文本消息中的释义检测的深度网络模型(IPM, 2018)
论文原标题 A deep network model for paraphrase detection in short text messages 摘要 本文研究释义检测,即识别语义相同的句子。检测用自然语言编写的相似句子的能力对一些应用程序至关重要,如文本挖掘、文本摘要、剽窃检测、作者身份认证和问题回答。认识到这一…...
鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:Web)下篇
onRequestSelected onRequestSelected(callback: () > void) 当Web组件获得焦点时触发该回调。 示例: // xxx.ets import web_webview from ohos.web.webviewEntry Component struct WebComponent {controller: web_webview.WebviewController new web_webv…...
5种认知减负策略:2025年macOS效率工具深度测评与工作流优化指南
5种认知减负策略:2025年macOS效率工具深度测评与工作流优化指南 【免费下载链接】Ice Powerful menu bar manager for macOS 项目地址: https://gitcode.com/GitHub_Trending/ice/Ice 在数字化工作环境中,macOS菜单栏作为系统与用户交互的核心界面…...
Qwen3.5-9B玩转YOLOv5:智能标注建议与模型训练参数调优
Qwen3.5-9B玩转YOLOv5:智能标注建议与模型训练参数调优 1. 引言:当大模型遇上目标检测 最近在做一个YOLOv5的目标检测项目时,遇到了两个头疼的问题:一是标注数据质量参差不齐影响模型效果,二是超参数调优耗费大量时间…...
seo代写文章的质量如何保证_seo代写文章的优势是什么
SEO代写文章的质量如何保证 在数字营销的世界里,SEO代写文章逐渐成为企业提升网站排名和吸引流量的重要工具。SEO代写文章的质量直接关系到网站的搜索引擎排名和用户体验。如何保证SEO代写文章的质量呢? 选择可靠的代写服务提供商是保证SEO代写文章质量…...
开关电源救星:用TVS二极管搞定MOS管击穿问题(以24V推挽电路为例)
开关电源救星:用TVS二极管搞定MOS管击穿问题(以24V推挽电路为例) 在中小功率开关电源设计中,MOS管击穿是工程师最头疼的故障之一。我曾在一个24V推挽式电源项目中,连续烧毁了5个MOS管,直到用示波器捕捉到那…...
如何突破音频收听限制?打造个人离线音频库的完整方案
如何突破音频收听限制?打造个人离线音频库的完整方案 【免费下载链接】xmly-downloader-qt5 喜马拉雅FM专辑下载器. 支持VIP与付费专辑. 使用GoQt5编写(Not Qt Binding). 项目地址: https://gitcode.com/gh_mirrors/xm/xmly-downloader-qt5 作为音频爱好者&a…...
【FineBI】自定义地图制作全流程:从数据导入到可视化优化
1. 数据准备与导入:从Excel到FineBI的完美衔接 第一次用FineBI做自定义地图时,最让我头疼的就是数据导入环节。后来发现只要掌握几个关键点,整个过程能节省至少半小时。首先确保Excel数据表满足这三个条件:第一列必须是区域名称&a…...
Cloudflare防火墙实战:5个高效规则提升网站安全与性能
1. Cloudflare防火墙:你的网站安全第一道防线 第一次接触Cloudflare防火墙时,我完全被它强大的功能震撼到了。作为一个免费工具,它能拦截90%以上的恶意流量,这简直是小站长的福音。记得去年我的个人博客突然遭遇一波CC攻击&#x…...
QQ空间历史说说一键导出终极指南:GetQzonehistory完整备份解决方案
QQ空间历史说说一键导出终极指南:GetQzonehistory完整备份解决方案 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 你是否曾想永久保存QQ空间里的青春记忆?那些深…...
RAGENativeUI:面向GTA模组开发的原生级界面框架架构分析
RAGENativeUI:面向GTA模组开发的原生级界面框架架构分析 【免费下载链接】RAGENativeUI 项目地址: https://gitcode.com/gh_mirrors/ra/RAGENativeUI 技术痛点深度剖析:GTA模组界面开发的现实挑战 在Grand Theft Auto V模组开发领域,…...
大模型微调实战:从SFT到RLHF的保姆级指南(含数据量建议)
大模型微调实战:从SFT到RLHF的保姆级指南(含数据量建议) 1. 为什么需要微调大模型? 想象一下,你刚拿到一台全新的智能手机,系统自带的功能已经足够强大,但如果你想让它更好地适应你的个人习惯—…...
