Redis压缩列表

news2024/10/6 18:12:49

区分一下

3.2之前 Redis中的List有两种编码格式 一个是LINKEDLIST 一个是ZIPLIST 这个ZIPLIST就是压缩列表

3.2之后来了一个QUICKLIST QUICKLIST是ZIPLIST和LINKEDLIST的结合体 也就是说Redis中没有ZIPLIST和LINKEDLIST了 然后在Redis5.0引入了LISTPACK用来替换QUiCKLIST中的ZIPLIST在REDIS7.0后完全取代了ZIPLIST

我们有说到压缩列表是List的底层数据结构,压缩列表主要用做为底层数据结构提供紧凑型的数据存储方式,能节约内存(节省链表指针的开销),小数据量的时候遍历访问性能好(连续+缓存命中率友好)。数据量少的时候会用它 

什么情况是数据量小的呢

1.列表对象保存的所有字符串对象长度都小于64字节;

2.列表对象元素个数少于512个,注意,这是LIST的限制,而不是ZIPLIST的限制;

满足以上两点 就会用ZIPLIST编码

ZIPLIST结构

zlbytes:表示该ZIPLIST一共占了多少字节数,这个数字是包含zlbytes本身占据的字节的。(夺大!)

zltail:ZIPLIST 尾巴节点相对于ZIPLIST的开头(起始指针)偏移的字节数。通过这个字段可以快速定位到尾部节点,例如现在有一个ZIPLIST,zl指向它的开头,如果要获取tail尾巴节点,即ZIPLIST里的最后一个节点,可以zl + zltail的值,这样定位到它。如果没有尾节点,就定位到 zlend

zllen:表示有多少个数据节点,在本例中就有3个节点。

entry1~entry3:表示压缩列表数据节点。

zlend:一个特殊的entry节点,表示ZIPLIST的结束。

ZIPLIST节点结构

就是上面的entry1 entry2....

他里面有三个字段

prevlen:表示上一个节点的数据长度。

encoding:编码类型。编码类型里还包含了一个entry的长度信息,可用于正向遍历

entry-data:实际的数据。

prevlen:

通过这个字段可以定位上一个节点的起始地址(或者说开头)也就是就是p-prevlen 可以跳到前一个节点的开头位置,实现从后往前操作,所以压缩列表才可以从后往前遍历。如果前一节点的长度,也就是前一个ENTRY的大小,小于254字节,那么prevlen属性需要用1字节长的空间来保存这个长度值,255是特殊字符,被zlend使用了如果前一节点的长度大于等于254字节,那么prevlen属性需要用5字节长的空间来保存这个长度值注意5个字节中中第一个字节为11111110,也就是254,标志这是个5字节的prelen信息,剩下4字节来表示大小。(这也差太多了 看人家MYSQL里面的可变长度列 少了就1字节 长了就2字节)

encoding:

00pppppp  1字节 String类型,且字符串长度小于2へ6,即小于等于63

 01pppppplqqqqqqqq  2字节 String类型,长度小于2^14次方,即小于等于16383

10000000|qqqqqqqq|rrrrrrrr|ssssssss|tttttttt 5字节 String类型,长度小于2へ32次方

110000001 2个字节的 int16类型

110100001 4个字节的 int32类型

11111110     1个字节的 int64类型

费老劲了 别背 就记住前几位是标识类型 后几位标识长度 对于int类型只标识类型 长度不用标

ZIPLIST性能

查询数据总量

由于ZIPLIST的header定义了记录节点数量的字段zllen,所以通常是可以在O(1)时间复杂度直接返回的,但是呢 zllen是两个字节的 也就是说最多也就能存65534的长度 大于了就存不下了 就得遍历了

遍历去吧 大于65534的节点数 累死 所以他只是应用节点数少的时候

查询指定节点

在ZIPLIST中查询指定数据的节点,需要遍历这个压缩列表,平均时间复杂度是O(N)。

更新数据

ZIPLIST的更新就是增加、删除数据,ZIPLIST提供头尾增减的能力,但是操作平均时间复杂度是O(N),因为在头部增加一个节点会导致后面节点都往后移动,所以更新的平均时间复杂度,可以看作O(N)。其中要注意的是更新操作可能带来连锁更新。注意上面所说的增加节点导致后移,不是连锁更新。连锁更新是指这个后移,发生了不止一次,而是多次。比如增加一个头部新节点,后面依赖它的节点,需要prevlen字段记录它的大小,原本只用1字节记录,因为更新可能膨胀为5字节,然后这个entry的大小就也膨胀了。所以,当这个新数据插入导致的后移完成之后,还需要逐步迭代更新。这种现象就是连锁更新,时间复杂度是O(Nへ2),6.2已经优化为O(N),不用太过担心连锁更新的情况,实际的业务中,很少会刚好遇到需要迭代更新超过2个节点的情况,所以ZIPLIST更新平均时间复杂度,还是可以看作O(N)。不过,ZIPLIST最大的问题还是连锁更新导致性能不稳定。

LISTPACK优化

优化了连锁更新

LISTPACK是为了解决ZIPLIST最大的痛点——连锁更新,我们先来看,ZIPLIST的问题本源。我们知道,ZIPLIST需要支持LIST,LIST是一种双端访问结构,所以需要能从后往前遍历,上面有讲,ZIPLIST的数据节点的结构是这样的:

<prevlen> <encoding> <entry-data>

其中,prevlen就表示上一个节点的数据长度,通过这个字段可以定位上一个节点的数据,可以说,连锁更新问题,就是因为prevlen导致的。

所以我们需要一种不记录prevlen,并且还能找到上一个节点的起始位置的办法,Redis使用了很巧妙的一种方式。我们直接看LISTPACK的节点定义:

1 <encoding-type><element-data><element-tot-len>

encoding-type是编码类型

element-data是数据内容

element-tot-len存储整个节点除它自身之外的长度。

element-tot-len 所占用的每个字节的第一个bit用于标识是否结束。0是结束,1是继续,剩下7个bit来存储数据大小。当我们需要找到当前元素的上一个元素时,我们可以从后向前依次查找每个字节,找到上一个Entry的element-tot-len 字段的结束标识,就可以算出上一个节点的首位置了。举个例子:如果上个节点的element-tot-len为00000001 10000100,每个字节第一个bit标志是否结束,所以这里的element-tot-len一共就两个字节,大小为00000010000100,即132字节。

一些QS

1.ZIPLIST有什么优点

首先肯定是相对于LINKEDLIST

1.节约内存,内存利用率高 2.方便一次性分配 3.遍历时局部性更强

2.ZIPLIST是怎么压缩数据的?

就是看它的结构

然后entry的结构是

他里面的这个entry是紧密相连的 

 3.ZIPLIST下List可以从后往前和从前往后遍历吗

可以 它是双端队列结构 从结构分析 它里面有个encoding结构 包含了长度信息 实现了正向遍历

prelen上一个节点的长度 实现了反向遍历

4.压缩列表插入的时间复杂度是多少?

头部插入是O(N)  他要把后面的数据往后挤  尾部插入O(1)

5.连锁更新的原因如何解决

就跟多米诺骨牌似的 如果上一个节点小于254字节 那下一个节点的prevlen是1长度 要是正好处于这个阈值 更新到了255 那下一个节点就得提升4个字节 那下一个节点也可能提升 balabla

解决就是别保存上一个节点长度 LISTPACK记录的当前节点的长度

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

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

相关文章

Windows下使用Maven命令打包Java后台代码

文章目录 1 JDK 环境变量配置2 Maven 环境变量配置3 Maven 命令打包3.1 清除之前打好的包3.2 直接打包3.3 跳过单元测试进行打包 1 JDK 环境变量配置 在 Windows 下配置 JDK 的环境变量可以按照以下步骤进行&#xff1a; 首先&#xff0c;确保已经安装了 JDK。可以从 Oracle …

SpringCloud实用篇2——Nacos配置管理 Feign远程调用 Gateway服务网关

目录 1 Nacos配置管理1.1 统一配置管理1.1.1 在nacos中添加配置文件1.1.2 从微服务拉取配置 1.2 配置热更新1.2.1 方式一1.2.2 方式二&#xff08;推荐&#xff09; 1.3.配置共享 2 搭建Nacos集群2.1 集群结构图2.2 搭建集群2.2.1 初始化数据库2.2.2 下载nacos2.2.3 配置Nacos2…

大文件传输软件| 生命科学中的关键因素

在2023年&#xff0c;生命科学领域以及其先进的科学技术吸引了人们的目光。这些研究背后&#xff0c;很少有人知道的是&#xff0c;其中涉及了大量的研究数据需要实时进行文件传输&#xff0c;以便于研究&#xff0c;合作&#xff0c;分享&#xff0c;分析&#xff0c;临床试验…

Nat、端口映射、内网穿透有什么区别?

简单地说端口映射、nat、内网穿透都是一个意思&#xff0c;同样的目的是解决跨网问题&#xff0c;同样涉及网络地址转换&#xff0c;如果要将内网服务器发布外网访问&#xff0c;就会用到其中一种方式。 细致地说&#xff0c;端口映射、nat、内网穿透又有所区别&#xff0c;端…

03_012slab块分配器,管理内核内存分配,管理高速缓存

物理背景 为什么会有缓存cache 在最初开发ARM架构时&#xff0c;处理器的时钟速度和内存的访问速度大致相同。今天的处理器内核要复杂得多&#xff0c;其时钟速度可以快上几个数量级。但是&#xff0c;外部总线和内存设备的频率并没有扩大到同样的程度。有可能实现小块的片上S…

Object Map 的相互转换

学生业务对象定义&#xff1a;Student Student student new Student(); student.setId(1L); student.setName("令狐冲") student.setAge(10) 第一种&#xff1a;通过Alibaba Fastjson实现 pom.xml 文件依赖 <dependency><groupId>com.alibaba</g…

js-7:javascript原型、原型链及其特点

1、原型 JavaScript常被描述为一种基于原型的语言-每个对象拥有一个原型对象。 当试图访问一个对象的属性时&#xff0c;它不仅仅在该对象上搜寻&#xff0c;还会搜寻该对象的原型&#xff0c;以及该对象的原型的原型&#xff0c;依次层层向上搜索&#xff0c;直到找到一个名字…

【使用内网穿透从公网对本地内网Web服务器访问】

公网访问本地内网web服务器【内网穿透】 文章目录 公网访问本地内网web服务器【内网穿透】前言1. 首先安装PHPStudy2.下载一个开源的网页文件3. 选择“创建网站”并将网页内容指向下载好的开源网页文件4. 打开本地网页5. 打开本地cpolar客户端6. 保存隧道设置 生成数据隧道 前言…

小模型赋能大电网,手机拍照来建档

电能计量箱&#xff0c;一个听上去陌生&#xff0c;看到却一定觉得熟悉的东西。 作为电力系统中的关键组成部分&#xff0c;电能计量箱被广泛安装在各类生产生活区域&#xff0c;保护其内部的电能表、互感器等计量装置的安全&#xff0c;是保障电力系统稳定运行的重要设施。随…

MATLAB(R2023a)添加工具箱TooLbox的方法-以GPOPS为例

一、找到工具箱存放位置 首先我们需要找到工具箱的存放位置&#xff0c;点击这个设置路径可以看到 我们的matlab工具箱的存放位置 C:\Program Files\MATLAB\R2023a\toolbox\matlab 从资源管理器中打开这个位置&#xff0c;可以看到里面各种工具箱 二、放入工具箱 解压我们…

ZABBIX 6.4配置企业微信告警

配置企业微信告警 1、将这2个微信配置文件复制到 /usr/local/share/zabbix/alertscripts zabbix6.4企业微信告警脚本文件&#xff1a;wechat.py zabbix6.4企业微信告警脚本文件&#xff1a;zabbix_wechat_config.json 2、修改文件权限 cd /usr/local/share/zabbix/alertscr…

C语言 — 动态内存管理(动态内存函数)

前言 本期分为三篇介绍动态内存管理相关内容&#xff0c;关注博主了解更多 博主博客链接&#xff1a;https://blog.csdn.net/m0_74014525 本期介绍动态内存函数&#xff0c;函数如何使用、函数格式、在使用在所需要的注意点及C/C程序的内存开辟区域 系列文章 第一篇&#xff…

node.js安装

下载 https://nodejs.org/en 安装 D:\Program Files\nodejs 配置 D:\Program Files\nodejs 目录下新建 node_cache 和 node_global 在cmd管理员身份运行&#xff1a; npm config set prefix "D:\Program Files\nodejs\node_global" npm config set cache &qu…

Qt中ffmpeg API存储和显示摄像头视频

Qt中ffmpeg API存储和显示摄像头视频的功能需要之前写的视频ffmpegAPI的视频播放的流程。 代码源码位置&#xff1a;https://download.csdn.net/download/qq_43812868/88157743?spm1001.2014.3001.5503 一、存储和显示摄像头的视频的流程 这是读取打开视频文件的流程&#x…

《吐血整理》高级系列教程-吃透Fiddler抓包教程(36)-掌握Fiddler中FiddlerScript用法你会有多牛逼-上

1.简介 Fiddler是一款强大的HTTP抓包工具&#xff0c;它能记录所有客户端和服务器的http和https请求&#xff0c;允许你监视&#xff0c;设置断点&#xff0c;甚至修改输入输出数据. 使用Fiddler无论对开发还是测试来说&#xff0c;都有很大的帮助。Fiddler提供的功能基本上能…

windows环境下如何更改pip安装的默认位置

1.查看配置信息 python -m site2.查看配置文件位置 python -m site -help3.修改配置文件 USER_SITE "D:\\soft\\Anaconda\\Lib\\site-packages" USER_BASE "D:\\soft\\Anaconda\\Scripts"如果遇到文件无法保存情况&#xff0c;请给用户增加权限。 4.…

STM32F103ZET6最小系统原理图及pcb文件

资料下载地址&#xff1a;STM32F103ZET6最小系统原理图及pcb文件 一、原理图 二、PCB

401 · 排序矩阵中的从小到大第k个数

链接&#xff1a;LintCode 炼码 - ChatGPT&#xff01;更高效的学习体验&#xff01; 题解&#xff1a; 九章算法 - 帮助更多程序员找到好工作&#xff0c;硅谷顶尖IT企业工程师实时在线授课为你传授面试技巧 class Solution { public:/*** param matrix: a matrix of intege…

Ctfshow web入门 XXE 模板注入篇 web373-web378 详细题解 全

CTFshow XXE web373 学习资料&#xff1a; &#xff08;梭哈~&#xff09; https://www.cnblogs.com/20175211lyz/p/11413335.html https://www.cnblogs.com/zhaijiahui/p/9147595.html https://www.cnblogs.com/r00tuser/p/7255939.html https://mp.weixin.qq.com/s?__bizMz…

51单片机程序烧录教程

STC烧录步骤 &#xff08;1&#xff09;STC单片机烧录方式采用串口进行烧录程序&#xff0c;连接的方式如下图&#xff1a; &#xff08;2&#xff09;所以需要先确保USB转串口驱动是识别到&#xff0c;且驱动运行正常&#xff1b;是否可通过电脑的设备管理器查看驱动是否正常…