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…...
日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...
站群服务器的应用场景都有哪些?
站群服务器主要是为了多个网站的托管和管理所设计的,可以通过集中管理和高效资源的分配,来支持多个独立的网站同时运行,让每一个网站都可以分配到独立的IP地址,避免出现IP关联的风险,用户还可以通过控制面板进行管理功…...
FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...
Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...
