Redis数据结构——QuickList、SkipList、RedisObjective

news/2024/5/15 16:05:46/文章来源:https://blog.csdn.net/TiankkTT/article/details/130788567

承接上文,本文主要介绍QuickList、SkipList、RedisObjective

四、 Redis数据结构-QuickList

问题1:ZipList虽然节省内存,但申请内存必须是连续空间,如果内存占用较多,申请内存效率很低。怎么办?

​ 答:为了缓解这个问题,我们必须限制ZipList的长度和entry大小。

问题2:但是我们要存储大量数据,超出了ZipList最佳的上限该怎么办?

​ 答:我们可以创建多个ZipList来分片存储数据。

问题3:数据拆分后比较分散,不方便管理和查找,这多个ZipList如何建立联系?

​ 答:Redis在3.2版本引入了新的数据结构QuickList,它是一个双端链表,只不过链表中的每个节点都是一个ZipList。
在这里插入图片描述

为了避免QuickList中的每个ZipList中entry过多,Redis提供了一个配置项:list-max-ziplist-size来限制。
如果值为正,则代表ZipList的允许的entry个数的最大值
如果值为负,则代表ZipList的最大内存大小,分5种情况:

  • -1:每个ZipList的内存占用不能超过4kb。
  • -2:每个ZipList的内存占用不能超过8kb。
  • -3:每个ZipList的内存占用不能超过16kb。
  • -4:每个ZipList的内存占用不能超过32kb。
  • -5:每个ZipList的内存占用不能超过64kb。

其默认值为 -2:
在这里插入图片描述

以下是QuickList的和QuickListNode的结构源码:

typedef struct quicklist {//头节点指针quicklistNode *head;//尾节点指针quicklistNode *tail;//所有ziplist的entry的数量unsigned long count;l//ziplists总数量unsigned long len;//ziplist的entry上限,默认值-2int fill : QL_FILL_BITS;//首尾不压缩的节点数量unsigned int compress : QL_COMP_BITS;//内存重分配时的书签数量及数组,一般用不到unsigned int bookmark_count: QL_BM_BITS;quicklistBookmark bookmarks[;
} quicklist;typedef struct quicklistNode {//前一个节点指针struct quicklistNode *prev;//下一个节点指针struct quicklistNode *next;//当前节点的ZipList指针unsigned char *zl;//当前节点的ZipList的字节大小unsigned int sz;//当前节点的ZipList的entry个数unsigned int count : 16;//编码方式:1,ZipList; 2,Izf压缩模式unsigned int encoding : 2;//数据容器类型(预留): 1,其它;2,ZipListunsigned int container : 2;//是否被解压缩。1︰则说明被解压了,将来要重新压缩unsigned int recompress : 1;unsigned int attempted_compress : 1;//测试用unsigned int extra : 10;/*预留字段*/
} quicklistNode;

我们接下来用一段流程图来描述当前的这个结构

在这里插入图片描述

总结:

QuickList的特点:

  • 是一个节点为ZipList的双端链表。
  • 节点采用ZipList,解决了传统链表的内存占用问题。
  • 控制了ZipList大小,解决连续内存空间申请效率问题。
  • 中间节点可以压缩,进一步节省了内存。

五、 Redis数据结构-SkipList

SkipList(跳表)首先是链表,但与传统链表相比有几点差异:

  • 元素按照升序排列存储。
  • 节点可能包含多个指针,指针跨度不同。

在这里插入图片描述

//t_zset.c
typedef struct zskiplist {//头尾节点指针struct zskiplistNode *header, *tail;//节点数量unsigned long length;//最大的索引层级,默认是1int level;
}zskiplist;typedef struct zskiplistNode {sds ele; //节点存储的值double score;//节点分数,排序、查找用struct zskiplistNode *backward;//前一个节点指针struct zskiplistLevel {struct zskiplistNode *forward;//下—个节点指针unsigned long span;//索引跨度} leveli;//多级索引数组
} zskiplistNode;

在这里插入图片描述

小总结:

SkipList的特点:

  • 跳跃表是一个双向链表,每个节点都包含score和ele值。
  • 节点按照score值排序,score值一样则按照ele字典排序。
  • 每个节点都可以包含多层指针,层数是1到32之间的随机数。
  • 不同层指针到下一个节点的跨度不同,层级越高,跨度越大。
  • 增删改查效率与红黑树基本一致,实现却更简单。

六、Redis数据结构-RedisObject

Redis中的任意数据类型的键和值都会被封装为一个RedisObject,也叫做Redis对象,源码如下:

1、什么是redisObject:
从Redis的使用者的角度来看,⼀个Redis节点包含多个database(非cluster模式下默认是16个,cluster模式下只能是1个),而一个database维护了从key space到object space的映射关系。这个映射关系的key是string类型,⽽value可以是多种数据类型,比如:string, list, hash、set、sorted set等。我们可以看到,key的类型固定是string,而value可能的类型是多个。
⽽从Redis内部实现的⾓度来看,database内的这个映射关系是用⼀个dict来维护的。dict的key固定用⼀种数据结构来表达就够了,这就是动态字符串sds。而value则比较复杂,为了在同⼀个dict内能够存储不同类型的value,这就需要⼀个通⽤的数据结构,这个通用的数据结构就是robj,全名是redisObject。

在这里插入图片描述

Redis的编码方式

Redis中会根据存储的数据类型不同,选择不同的编码方式,共包含11种不同类型:

编号编码方式说明
0OBJ_ENCODING_RAWraw编码动态字符串
1OBJ_ENCODING_INTlong类型的整数的字符串
2OBJ_ENCODING_HThash表(字典dict)
3OBJ_ENCODING_ZIPMAP已废弃
4OBJ_ENCODING_LINKEDLIST双端链表
5OBJ_ENCODING_ZIPLIST压缩列表
6OBJ_ENCODING_INTSET整数集合
7OBJ_ENCODING_SKIPLIST跳表
8OBJ_ENCODING_EMBSTRembstr的动态字符串
9OBJ_ENCODING_QUICKLIST快速列表
10OBJ_ENCODING_STREAMStream流

五种数据结构

Redis中会根据存储的数据类型不同,选择不同的编码方式。每种数据类型的使用的编码方式如下:

数据类型编码方式
OBJ_STRINGint、embstr、raw
OBJ_LISTLinkedList和ZipList(3.2以前)、QuickList(3.2以后)
OBJ_SETintset、HT
OBJ_ZSETZipList、HT、SkipList
OBJ_HASHZipList、HT

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

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

相关文章

C++入门篇---(命名空间、缺省参数、以及输入、输出)

前言 c 我来了,恭喜牛牛解锁新世界.开启c的学习之旅. 🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨ 🐻推荐专栏: 🍔🍟🌯C语言进阶 🔑个人信条: 🌵知行合一 🍉本篇简介:>:讲解C…

pg事务:子事务

什么是子事务? 一般事务只能整体提交或回滚,而子事务允许部分事务回滚。 SAVEPOINT p1 在事务里面打上保存点标记。不能直接提交子事务,子事务也是通过事务的提交而提交。不过可以通过ROLLBACK TO SAVEPOINT p1回滚到该保存点。 子事务在大…

【场景方案】如何去设计并二次封装一个好用的axios,给你提供一个好的参考(1.0版)

文章目录 前言文件结构建议封装的文件结构接口管理文件 二次封装axios的初始配置initutilswebConfig 再封一层环境配置使用 前言 以下演示基于vue3与element-plus 文件结构建议 封装的文件结构 把二次封装axios所有有关的代码全部放在request文件夹中,其中init.js…

【TypeScript】TS中type和interface在类型声明时的区别

🐱 个人主页:不叫猫先生 🙋‍♂️ 作者简介:2022年度博客之星前端领域TOP 2,前端领域优质作者、阿里云专家博主,专注于前端各领域技术,共同学习共同进步,一起加油呀! 💫优质专栏:vue3+vite+typeScript从入门到实践 📢 资料领取:前端进阶资料可以找我免费领取 …

南京邮电大学算法与设计实验二:贪心算法(最全最新,与题目要求一致)

三、实验原理及内容 实验原理: 1、用贪心法实现求两序列的一般背包问题。要求掌握贪心法思想在实际中的应用,分析一般背包的问题特征,选择算法策略并设计具体算法,编程实现贪心选择策略的比较,并输出最优解和最优解值。…

机器学习项目实战-能源利用率 Part-4(模型构建)

博主前期相关的博客可见下: 机器学习项目实战-能源利用率 Part-1(数据清洗) 机器学习项目实战-能源利用率 Part-2(探索性数据分析) 机器学习项目实战-能源利用率 Part-3(特征工程与特征筛选) 这…

【JVM】6. 堆

文章目录 6.1. 堆(Heap)的核心概述6.1.1. 堆内存细分6.1.2. 堆空间内部结构(JDK7)6.1.3. 堆空间内部结构(JDK8) 6.2. 设置堆内存大小与OOM6.2.1. 堆空间大小的设置6.2.2. OutOfMemory举例 6.3. 年轻代与老年…

如何在IDEA中显示时序图

如何在IDEA中显示时序图 有时候,我们想要了解代码的运行过程的时候,想要看到方法的调用流程。 这个时候就希望有一个时序图可以看,但是人工来画时序图太麻烦了,有没有办法在IDEA中直接生成呢? 当然是可以的。 这里…

知识积累(1)

(1) 当您在Git中看到消息 "HEAD is now at 1343ccb FAB-17419 Fix off_chain_data sample error (#146)" 时,这是Git告知您当前所在的分支和最新的提交哈希。 这条消息通常出现在使用Git命令后,如git pull或git check…

【我的创作纪念日】—— 纪念四年的坚持

这是一篇和技术无关的博客,但对我而言,它承载了不菲的价值 普通且宁静的一天,被一条消息戳中,于是,写一篇分享帖,纪念我这 1460 天的坚持初衷: 前言:对过去的回顾 4 年前的我&#…

Python图片转字符画,太好玩啦(46)

小朋友们好,大朋友们好! 我是猫妹,一名爱上Python编程的小学生。 和猫妹学Python,一起趣味学编程。 今日主题 什么是字符画呢? 如何用Python将图片转为字符画? 我们先找一幅原画,比如它吧&…

卡方检验.医学统计实例详解

卡方检验是一种常用的假设检验方法,通常用于分析两个或多个分类变量之间的关系。在医学研究中,卡方检验被广泛应用于分析两种或多种治疗方法的疗效,或者分析某种疾病的发病率与某些危险因素之间的关系。下面我们来看一个卡方检验在医学实例中…

WALN网络不存在? 离谱事件解决方法

前情: 本来在高高兴兴赶ddl,突然发现网断了。尝试重连,显示无法连接... 遂重启,结果事情更糟了,WALN就没了,没了,没了... 这张是修好之后的图,但是当时所有包括蓝牙,waln…

13-2-CSS3-渐变色、2D转换、3D转换

一、渐变色 CSS渐变色(Gradient)是指在元素背景中使用两种或多种不同的颜色进行过渡,超过两个颜色可以形成更为细腻的渐变效果。常见的CSS渐变色有线性渐变和径向渐变。 1. 线性渐变:Linear Gradients 向下/向上/向左/向右/对角…

t检验与Z检验的区别

在统计学中,假设检验是评估某种特定情况下观察到的数据是否符合假设的一种方法。t检验和Z检验是两种常用的假设检验方法,分别用于比较均值差异以及比例差异。在医学统计中,t检验和Z检验经常被用于研究和比较不同治疗方法的效果,例…

基于MAC地址的ACL配置

基于MAC地址的ACL配置 【实验目的】 掌握基于MAC地址的标准ACL的配置。验证配置。 【实验拓扑】 实验拓扑如图1所示。 图1 实验拓扑 设备参数如表所示。 表1 设备参数表 设备 接口 IP地址 子网掩码 默认网关 S1 e0/0 N/A N/A N/A e0/1 N/A N/A N/A PC1 N/…

IntelliJ 导出和导入配置文件

导出: File->Manage IDE Setting->Export Settings…->选择导出目录,可以得到一个 settings.zip 的文件 导入方法: File->Manage IDE Setting->Import Settings…->选择需要导入的文件即可,导入之后重启IDE。

chatgpt赋能Python-pythonfind

Python文件搜索工具Pythonfind 在开发过程中,文件搜索工具是一个非常重要的工具。在大型项目中,可能需要查找特定类型的文件或者在代码库中查找特定的代码块。 Pythonfind是一个非常强大和灵活的python文件搜索工具,可以帮助我们简化这个过程…

Go 语言核心编程-环境入门篇

第 1 章 Golang 开山篇 1.1 Golang 的学习方向 Go 语言,我们可以简单的写成 Golang 1.2 Golang 的应用领域 1.2.1区块链的应用开发 1.2.2后台的服务应用 1.2.3云计算/云服务后台应用 1.3 学习方法的介绍 1.4 讲课的方式的说明 努力做到通俗易懂注重 Go 语言体系&…

云从科技从容大模型:大模型和AI平台什么关系?为什么造行业大模型?

原创:亲爱的数据 2023年5月18日,坐标广州南沙,来自云从科技的“云从从容大模型”正式亮相。 自此,云从科技从CV四小龙“进阶”成为一家AI大模型公司,同时,别忘记云从还有一个身份常被人提起:首家…