Redis数据结构ZipList,QuickList,SkipList

目录

1.ZipList

1.2.解析Entry:

1.3Encoding编码

1.4.ZipList连锁更新问题

2.QuickList

SkipList跳表

RedisObject

五种数据类型


1.ZipList

redis中的ZipList是一种紧凑的内存储存结构,主要可以节省内存空间储存小规模数据。是一种特殊的双端链表,有一系列连续的内存组成,可以在任意一端进行压入/弹出操作,而且操作的时间复杂度为O(1)

常见方法:

LPUSH mylist "value1" "value2"    //左边插入
RPUSH mylist "value3" "value4"    //右边插入LPOP mylist    //从链表最左端弹出数据
RPOP mylist    //从链表最右端弹出数据LRANGE mylist 0 2    //获取左边指定范围的数据
LINDEX mylist 0    //获取指定下标数据LLEN mylist    //获取列表长度
zlbyteszltailzllenentry

...

entryentryzlend
属性类型长度用途
zlbytesuint32_t4字节记录整个压缩链表占用的内存字节数
zltailuint32_t4字节这个是偏移量,记录压缩列表尾节点到列表起始地址有多少字节,通过这个偏移量,可以确定尾节点地址
zllenuint16_t2字节记录列表包含的节点数量。最大65534,如果超出也只是65535
entry列表节点不定各个节点的长度由节点保存的内容确定
zlenduint8_t1字节特殊值0xFF(255),用于标记压缩例表的末端
1.2.解析Entry:

ZipList的Entry不像普通链表那样记录前后节点的指针,因为记录前后节点指针需要16字节,大大浪费了内存。所以采用下面的结构来保存。

previous_entry_lengthencoding

content

1.previous_entry_length:前一节点的长度,占1字节 或 5字节

当前一节点长度 < 254字节,采用 1字节保存这个长度值

当前一节点的长度 > 254字节,采用5字节保存这个长度值

2.encoding:编码属性,记录content的数据类型(数字/字符串)及长度,占用1,2,5字节。

3.contents:负责保存具体的内容,可以是数字可以是字符串

注意:ZipList中所有储存长度的数值均采用小端字节序储存,低位在前,高位字节在后。

列如:0x1234,采用小端字节序后就是 0x3412

1.3Encoding编码

encoding编码分为两种:字符串和数字

字符串:encoding以00,01,10开头标识储存的是字符串。

下面长度不同的字符串对应encoding编码格式

举例:储存字符串ab,bc

1.4.ZipList连锁更新问题

ZipList的每个Entry都包含previous_entry_length来记录上一节点大小,长度为1个或5字节。

>>如果前一节点长度 < 254,那么采用1字节保存这个长度值。

>>如果前一节点 >= 254,则采用5字节保存这个长度值。

如果有N个连续的长度为250~253之间的entry,如果不巧有一个扩展那么又可能发生连锁反应,又可能所有都发生连锁更新,新增,删除都可能导致连锁更新发生

总结:

1.压缩列表可以看作连续内存空间的“双向链表“

2.列表的节点之间不是通过指针链接,而是上一节点和本节点长度来寻址,大大节省内存

3.如果数据过多,链表过长,可能影响查询性能

4.增加删除都可能发生连续更新问题


2.QuickList

ZIpList虽然节省内存,但是申请内存必须是连续空间,如果内存占用过多那么申请效率变低

数据量过大超出上限采用分片储存数据,那么这些ZipList如何联系?

Redis3.2版本引入QuickList,是一个双端链表,只不过每个节点都是ZipList

Redis提供配置:list-max-ziplist-size 

如果值是正:代表ZipList允许的最大entry数。

如果值是负:代表每个ZipList的最大内存大小。

-1-2-3-4-5
4kb8kb16kb32kb64kb

QuickList可以控制首尾是否进行压缩,通过配置项list-compress-depth来控制,这个参数是控制首尾不压缩的节点个数。

012
代表首尾节点不压缩首尾各有一个1个不压缩,中间全压缩首尾各有2节点不压缩,中间全压缩

QuickList 和 Quick List Node的结构源码:

QuickList结构图:

QuickList特性:

1.每个节点都是ZipList的双端链表

2.节点采用ZipList,解决传统链表的内存占用

3.控制ZipList大小,解决传统连续内存空间申请问题

4.中间节点可压缩,节省内存


SkipList跳表

是个链表,但不是普通链表,不同节点之间跨度不一样。

1.元素按照升序排列储存

2.节点可能包含多个指针,指针跨度不同

为了更快的找到所需要的元素,SkipList采用这种结构类似于二分查找。

以下是结构源码:

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

特性:

1.跳表是一个双向链表,每个节点包含存储的值和排序用的socre,用来保存别的节点的ele数组

2.节点按照score值排序,score值一样按照ele字典排序

3.每层指针到下一节点跨度不同,层级越高跨度越大

4.增删改查的效率与红黑树基本一致


RedisObject

在Redis中任意数据类型的键和值都会被封装在一个RedisObject中,也叫做Redis对象。

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

编号编码方式说明
0OBJ_ENCODING_RAW动态字符串(动态长度,非预分配)
1OBJ_ENCODING_INT长整型(用 long 类型存储)
2OBJ_ENCODING_HT哈希表(字典,基于 dict 实现)
3OBJ_ENCODING_ZIPMAP已废弃的哈希压缩结构
4OBJ_ENCODING_LINKEDLIST双端链表(旧版 List 实现)
5OBJ_ENCODING_ZIPLIST压缩列表(紧凑的二进制结构)
6OBJ_ENCODING_INTSET整数集合(仅存储整数的有序集合)
7OBJ_ENCODING_SKIPLIST跳表(有序集合的底层实现之一)
8OBJ_ENCODING_EMBSTR短字符串(固定长度,预分配内存)
9OBJ_ENCODING_QUICKLIST快速列表(双向链表 + 压缩列表)
10OBJ_ENCODING_STREAMStream 流(消息队列结构)

五种数据类型

String基于简单动态字符串SDS实现,存储上限为512mb,基本编码方式是RAM

List可以从首尾操作列表中的元素,3.2版本后统一采用QuickList来实现List

Set:

1.为了查询效率和唯一性,采用Dict编码,key为存储元素,value统一为null

2.所有数据都是整数,且元素数量不超过set-max-intset-entries,Set会采用IntSet编码

ZSet:

ZSet就是SortedSet,其中每个元素都需指定一个score 和 member值

可以根据score排序,且member必须唯一,可以根据member查询分数

当元素数数量小时,采用ZipList来节省内存,但是需要满足两个条件:

1.元素数量小于 zset_max_ziplist_entries (128)

2.每个元素都小于zset_max_ziplist_value(64)

当数据量大时采用SkipList和HT结构

Hash:

hash底层的编码和ZSet基本一致,只需要把排序有关的SkipList去掉就行。

1.数据量小时,采用ZipList编码节省内存,ZipList中相邻的两个entry保存field和value

2.数据量大时,采用HT编码,就是Dict,触发条件是:元素数量超过512,每个entry超过64字节

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

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

相关文章

laravel 12 监听syslog消息,并将消息格式化后存入mongodb

在Laravel 12中实现监听Syslog消息并格式化存储到MongoDB&#xff0c;需结合日志通道配置、Syslog解析和MongoDB存储操作。以下是具体实现方案&#xff1a; 一、环境配置 安装MongoDB扩展包 执行以下命令安装必要的依赖&#xff1a; composer require jenssegers/mongodb ^4.0确…

【STM32项目实战】一文了解单片机的SPI驱动外设功能

前言&#xff1a;在前面我有文章介绍了关于单片机的SPI外设CUBEMX配置&#xff0c;但是要想使用好SPI这个外设我们还必须对其原理性的时序有一个详细的了解&#xff0c;所以这篇文章就补充一下SPI比较偏向底层的时序性的逻辑。 1&#xff0c;SPI简介 SPI是MCU最常见的对外通信…

【挖洞利器】GobyAwvs解放双手

【渗透测试工具】解放双手&Goby配合Awvs渗透测试利器\x0a通过Goby和Awvs 解放双手https://mp.weixin.qq.com/s/SquRK8C5cRpWmfGbIOqxoQ

LangChain4j(15)——RAG高级之跳过检索

之前的文章中&#xff0c;我们介绍了RAG的使用&#xff0c;但是&#xff0c;每次提问时&#xff0c;都会通过RAG进行检索。有时&#xff0c;检索是不必要执行的&#xff0c;比如&#xff0c;当用户只是说“你好”时。于是&#xff0c;我们需要有条件的跳过检索过程。 跳过决策…

【SDRS】面向多模态情感分析的情感感知解纠缠表征转移

abstract 多模态情感分析(MSA)旨在利用多模态的互补信息对用户生成的视频进行情感理解。现有的方法主要集中在设计复杂的特征融合策略来整合单独提取的多模态表示,忽略了与情感无关的信息的干扰。在本文中,我们提出将单模表征分解为情感特定特征和情感独立特征,并将前者融…

Sui 上线两周年,掀起增长「海啸」

两年前的 5 月 3 日&#xff0c;Sui 的主网正式发布&#xff0c;将在开发网和测试网上验证过的下一代技术承诺变为现实。这一新兴网络旨在优化现有区块链技术&#xff0c;结合高性能计算环境与安全性、可验证性及韧性。 随着 Sui 迎来两周年&#xff0c;这股浪潮已成长为「海啸…

深入理解 mapper-locations

mybatis-plus.mapper-locations: classpath*:/mapper/**/*.xml 是 MyBatis/MyBatis-Plus 在 Spring Boot 配置文件&#xff08;如 application.yml 或 application.properties&#xff09;中的一项关键配置&#xff0c;用于指定 MyBatis Mapper XML 文件的存放路径。以下是详细…

电容的作用

使用多个电容是从电容的实际等效模型去考虑的(也就是从SI&#xff0c;信号完整性方面&#xff09;。只考虑一个实际电容时&#xff0c;它的阻抗曲线是一个类似于倒三角形的形状&#xff0c;只在谐振频率点(与等效串联电感形成)处的阻抗最小。因此相当于只在这一个频率点处及附近…

移植的本质是什么

有断时间我就在想&#xff0c;为什么freertos&#xff0c;lvgl等等的移植都是把库文件放进来&#xff0c;直接点击编译&#xff0c;然后把bug都处理完成就移植成功了&#xff0c;为什么呢&#xff1f; 明明我一个函数都没调用&#xff0c;为什么会有一堆错误&#xff0c;莫名其…

广告场景下的检索平台技术

检索方向概述 数据检索领域技术选型大体分为SQL事务数据库、NoSQL数据库、分析型数据库三个类型。 SQL数据库的设计思路是采用关系模型组织数据&#xff0c;注重读写操作的一致性&#xff0c;注重数据的绝对安全。为了实现这一思路&#xff0c;SQL数据库往往会牺牲部分性能&…

高频PCB设计如何选择PCB层数?

以四层板为例&#xff0c;可以第一层和第二层画信号&#xff0c;作为信号层。 第三层可以走电源&#xff0c;然后第四层走GND 但是更可以第一层和第三层画信号。第二层可以走电源&#xff0c;然后第四层走GND 用中间的电源层以及地层可以起到屏蔽的作用&#xff0c;有效降低寄…

[Linux_69] 数据链路层 | Mac帧格式 | 局域网转发 | MTU MSS

目录 0.引入 1.以太网帧格式 2.重谈局域网转发的原理(基于协议) 小结 3.认识MTU 3.1MTU对IP协议的影响 3.2MTU对UDP协议的影响 3.3MTU对于TCP协议的影响 0.引入 在去年的这篇文章中&#xff0c;我们有对网络进行过一个概述[Linux#47][网络] 网络协议 | TCP/IP模型 | 以…

vue2 provide 后 inject 数据不是响应式的,不实时更新

今天用 provide 后&#xff0c;inject 获取数据时不是实时更新的&#xff0c;获取的不是更新后的值 祖父组件 <div style"text-align: left !important;"><button click"change">更改</button> </div>data() {return {name: ini…

洛谷---P1629 邮递员送信

题目描述 有一个邮递员要送东西&#xff0c;邮局在节点 1。他总共要送 n−1 样东西&#xff0c;其目的地分别是节点 2 到节点 n。由于这个城市的交通比较繁忙&#xff0c;因此所有的道路都是单行的&#xff0c;共有 m 条道路。这个邮递员每次只能带一样东西&#xff0c;并且运…

2025年LangChain(V0.3)开发与综合案例

LangChain是什么&#xff1f; 在实际企业开发中&#xff0c;大模型应用往往比简单的问答要复杂得多。如果只是简单地向大模型提问并获取回答&#xff0c;那么大模型的许多强大功能都没有被充分利用。 要开始使用LangChain&#xff0c;首先需要安装相关的库&#xff1a; pip …

十分钟了解 @MapperScan

MapperScan 是 MyBatis 和 MyBatis-Plus 提供的一个 Spring Boot 注解&#xff0c;用于自动扫描并注册 Mapper 接口&#xff0c;使其能够被 Spring 容器管理&#xff0c;并与对应的 XML 或注解 SQL 绑定。它的核心作用是简化 MyBatis Mapper 接口的配置&#xff0c;避免手动逐个…

深度解析 MindTorch:无缝迁移 PyTorch 到 MindSpore 的高效工具

在深度学习领域&#xff0c;框架的选择往往取决于开发者的习惯、硬件支持以及项目需求。PyTorch 作为当前最受欢迎的深度学习框架之一&#xff0c;以其动态图机制和简洁的 API 设计深受开发者喜爱。然而&#xff0c;随着昇腾硬件的崛起&#xff0c;如何高效地利用昇腾的强大计算…

[250506] Auto-cpufreq 2.6 版本发布:带来增强的 TUI 监控及多项改进

目录 Auto-cpufreq 2.6 版本发布&#xff1a;带来增强的 TUI 监控及多项改进 Auto-cpufreq 2.6 版本发布&#xff1a;带来增强的 TUI 监控及多项改进 Auto-cpufreq&#xff0c;一款适用于 Linux 的免费开源自动 CPU 速度与功耗优化器&#xff0c;已发布其最新版本 2.6。该工具…

Linux 更改内存交换 swap 为 zram 压缩,减小磁盘写入

1、查看当前 swap 的方式 swapon --show 我这里是默认的 swap 文件&#xff0c;大小为 2G。 2、安装 zram Ubuntu 下&#xff1a; sudo apt install zram-tools安装后默认会启动&#xff1a; 3、关闭默认的 swap 文件 sudo swapoff /swapfile 其次是关闭 /etc/fstab 中的 …

ORCAD打印pdf

1 笔记本电脑绑定了打印机&#xff0c;要改成这个