[redis] 说一说 redis 的底层数据结构

Redis有动态字符串(sds)链表(list)字典(ht)跳跃表(skiplist)整数集合(intset)压缩列表(ziplist) 等底层数据结构。
Redis并没有使用这些数据结构来直接实现键值对数据库,而是基于这些数据结构创建了一个对象系统,来表示所有的key-value。


文章目录

        • 1.1 字符串
        • 1.2 **链表linkedlist**
        • 1.3 哈希表 hashtable
        • 1.4 跳跃表skiplist
        • 1.5 整数集合intset
        • 1.6 压缩列表ziplist:压缩列表是为节约内存⽽开发的顺序性数据结构,它可以包含任意多个节点,每个节点可以保存⼀个字节数组或者整数值。
        • 1.7 quicklist (3.2)
        • 1.8 listpack (5.0)

我们常用的数据类型和编码对应的映射关系:

1.1 字符串

redis 没有直接使⽤ C 语⾔传统的字符串表示,⽽是⾃⼰实现的叫做简单动态字符串SDS的抽象类型。C 语⾔的字符串不记录⾃身的⻓度信息,⽽ SDS 则保存了⻓度信息,这样将获取字符串⻓度的时间由 O(N) 降低到了 O(1),同时可以避免缓冲区溢出和减少修改字符串⻓度时所需的内存重分配次数。

1.2 链表linkedlist

redis 链表是⼀个双向⽆环链表结构,每个链表的节点由⼀个 listNode 结构来表示,每个节点都有指向前置节点和后置节点的指针,同时表头节点的前置和表尾的后置节点都指向NULL。

1.3 哈希表 hashtable

一个哈希表里可以有多个哈希表节点,而每个哈希表节点就保存了字典里中的一个键值对。 每个字典带有两个hash表,供平时使⽤和 rehash 时使⽤,hash表使⽤链地址法来解决键冲突,被分配到同⼀个索引位置的多个键值对会形成⼀个单向链表,在对hash表进⾏扩容或者缩容的时候,为了服务的可⽤性,rehash的过程不是⼀次性完成的,⽽是渐进式的。

1.4 跳跃表skiplist

Redis跳跃表由 zskiplist 和 zskiplistNode 组成,zskiplist ⽤于保存跳跃表信息(表头、表尾节点、⻓度等),zskiplistNode ⽤于表示表跳跃节点,每个跳跃表节点的层⾼都是 1-32 的随机数,在同⼀个跳跃表中,多个节点可以包含相同的分值,但是每个节点的成员对象必须是唯⼀的,节点按照分值⼤⼩排序,如果分值相同,则按照成员对象的⼤⼩排序。

1.5 整数集合intset

⽤于保存整数值的集合抽象数据结构,不会出现重复元素,底层实现为数组。

1.6 压缩列表ziplist:压缩列表是为节约内存⽽开发的顺序性数据结构,它可以包含任意多个节点,每个节点可以保存⼀个字节数组或者整数值。

1.7 quicklist (3.2)

https://github.com/redis/redis/blob/unstable/src/quicklist.h#L46
quicklist 的设计,其实是结合了链表和 ziplist 各自的优势。简单来说,一个 quicklist 就是一个链表,而链表中的每个元素又是一个 ziplist。
image.png

typedef struct quicklist {quicklistNode *head;quicklistNode *tail;unsigned long count;        /* total count of all entries in all ziplists */unsigned long len;          /* number of quicklistNodes */int fill : 16;              /* fill factor for individual nodes */unsigned int compress : 16; /* depth of end nodes not to compress;0=off */
} quicklist;typedef struct quicklistNode {struct quicklistNode *prev;struct quicklistNode *next;unsigned char *zl;unsigned int sz;             /* ziplist size in bytes */unsigned int count : 16;     /* count of items in ziplist */unsigned int encoding : 2;   /* RAW==1 or LZF==2 */unsigned int container : 2;  /* NONE==1 or ZIPLIST==2 */unsigned int recompress : 1; /* was this node previous compressed? */unsigned int attempted_compress : 1; /* node can't compress; too small */unsigned int extra : 10; /* more bits to steal for future usage */
} quicklistNode;typedef struct quicklistEntry {const quicklist *quicklist;quicklistNode *node;unsigned char *zi;unsigned char *value;long long longval;unsigned int sz;int offset;
} quicklistEntry;
  • quicklist 是一个双向链表,head、tail分别指向头尾节点
  • quicklistNode 是双向链表的节点,prev、next分别指向前驱、后继结点
  • quicklistNode.zl 指向一个ziplist(或者quicklistLZF结构)
  • quicklistEntry 包裹着list的每一个值,作为ziplist的一个节点

可以想象得到,当一个空的quicklist加入一个值value时,会有以下操作(不一定以这个顺序):

  1. 使用Entry包裹value
  2. 创建一个ziplist,把Entry加入到ziplist中
  3. 创建一个Node,Node.zl指向ziplist
  4. 创建quicklist,将Node加入quicklist中
1.8 listpack (5.0)

而 Redis 除了设计了 quicklist 结构来应对 ziplist 的问题以外,还在 5.0 版本中新增了 listpack 数据结构,用来彻底避免连锁更新。
listpack 也叫紧凑列表,它的特点就是用一块连续的内存空间来紧凑地保存数据,同时为了节省内存空间,listpack 列表项使用了多种编码方式,来表示不同长度的数据,这些数据包括整数和字符串。

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

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

相关文章

76.网络游戏逆向分析与漏洞攻防-移动系统分析-分析角色移动产生的数据包

免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 如果看不懂、不知道现在做的什么,那就跟着做完看效果,代码看不懂是正常的,只要会抄就行,抄着抄着就能懂了 内容…

基于vue.js+thymeleaf模板引擎+ajax的注册登陆简洁模板(含从零到一详细介绍)

文章目录 前言1、数据库准备2、工具类与相关基类使用2.1、工具类2.2、相关基类 3、web包目录说明4、注册功能设计(本文核心部分)4.1、注册页面设计4.2、注册逻辑设计 5、登陆功能设计5.1、登陆页面设计5.2、登陆逻辑设计 6、运行效果图 前言 大多数的网…

JUC-synchronized练习-交替打印ABC

今天来练习一下synchronized 简单来利用synchronized实现一个字符串的交替打印 主要的实现设置一个全局的变量state,线程执行通过不断累加state,根据state对三取余的结果来判断该线程是否继续执行还是进入等待。并通过synchronized锁住一个共享变量loc…

C语言 自定义类型——联合体

目录: 一、联合体是?声明计算内存大小 二、联合体的特点例如 三、联合体大小的计算规则: 四、应用习1习2 一、联合体是? 联合体和结构体差不多,但是其最大的区别在于联合体所有的成员共用一块内存空间。所以联合体也叫共用体。联…

【MATLAB源码-第204期】基于matlab的语音降噪算法对比仿真,谱减法、维纳滤波法、自适应滤波法;参数可调。

操作环境: MATLAB 2022a 1、算法描述 语音降噪技术的目的是改善语音信号的质量,通过减少或消除背景噪声,使得语音更清晰,便于听者理解或进一步的语音处理任务,如语音识别和语音通讯。在许多实际应用中,如…

25-ESP32-S3 内置的真随机数发生器(RNG)

ESP32-S3 内置的真随机数发生器(RNG)😎 引言 📚 在许多应用中,随机数发生器(RNG)是必不可少的。无论是在密码学🔒、游戏🎮、模拟🧪或其他领域,随…

AGI|基于LangChain实现的三种高级RAG检索方法

一、前言 RAG(Retrieval-Augmented Generation)检索增强生成,是现如今基于企业私域知识的问答应用所使用的主流技术之一。相较于重新训练基于私域知识的大模型来说,RAG没有额外的预训练成本,且回答效果与之相当。 但在实际应用场景中&#xf…

自动化运维管理工具----------Ansible模块详细解读

目录 一、自动化运维工具有哪些? 1.1Chef 1.2puppet 1.3Saltstack 二、Ansible介绍 2.1Ansible简介 2.2Ansible特点 2.3Ansible工作原理及流程 2.3.1内部流程 2.3.2外部流程 三、Ansible部署 3.1环境准备 3.2管理端安装 ansible 3.3Ansible相关文件 …

目前最便宜的VPS多少钱一个月?

目前最便宜的VPS一个月的价格在5美元左右,换算成人民币约为35元。 VPS服务器的配置、性能、所在地区都是影响其价格的因素,价格与性能呈正相关,也有的廉价VPS的服务商会提供性能低的配置,让用户可以进行简单的网站托管或开发环境…

鸿蒙内核源码分析(进程通讯篇) | 九种进程间通讯方式速揽

进程间为何要通讯 ? 鸿蒙内核默认支持 64个进程和128个任务,由进程池和任务池统一管理.内核设计尽量不去打扰它们,让各自过好各自的日子, 但大家毕竟在一口锅里吃饭, 不可能不与外界联系, 联系就得有渠道&#xff0c…

ZIP压缩输出流(将ZIP文件解压)

文章目录 前言一、ZIP压缩输出流是什么?二、使用介绍 1.使用方法2.实操展示总结 前言 该篇文章相对应的介绍如何使用java代码将各种文件(文件夹)从ZIP压缩文件中取出到指定的文件夹中。解压流将ZIP文件中的文件以条目的形式逐一读取&#xff…

UE5自动生成地形二:自动生成插件

UE5自动生成地形二:自动生成插件 Polycam使用步骤 本篇主要讲解UE5的一些自动生成地形的插件 Polycam 此插件是通过现实的多角度照片自动建模生成地形数据,也是免费的。这里感谢B站up主古道兮峰的分享 Polycam网站 插件下载地址 插件网盘下载 提取码&a…