Redis压缩列表

区分一下

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.mzph.cn/news/24869.shtml

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

相关文章

【C++】深入浅出STL之vector类

文章篇幅较长&#xff0c;越3万余字&#xff0c;建议电脑端访问 文章目录 一、前言二、vector的介绍及使用1、vector的介绍2、常用接口细述1&#xff09;vector类对象的默认成员函数① 构造函数② 拷贝构造③ 赋值重载 2&#xff09;vector类对象的访问及遍历操作① operator[]…

学习左耳听风栏目90天——第一天 1-90(学习左耳朵耗子的工匠精神,对技术的热爱)【洞悉技术的本质,享受科技的乐趣】

洞悉技术的本质&#xff0c;享受科技的乐趣 第一篇&#xff0c;我的感受就是 耗叔是一个热爱技术&#xff0c;可以通过代码找到快乐的技术人。 作为it从业者&#xff0c;我们如何可以通过代码找到快乐呢&#xff1f;这是一个问题&#xff1f; 至少目前&#xff0c;我还没有这种…

Qt之C++

Qt之C 类的定义 C语言的灵魂是指针 C的灵魂是类&#xff0c;类可以看出C语言结构体的升级版&#xff0c;类的成员可以是变量&#xff0c;也可是函数。 class Box { public://确定类成员的访问属性double length;//长double breadth;//宽度double heigth;//高度 };定义对象 …

TestNG中实现多线程并行,提速用例的执行时间

TestNG是一个开源自动化测试工具&#xff0c;TestNG源于Junit&#xff0c;最初用来做单元测试&#xff0c;可支持异常测试&#xff0c;忽略测试&#xff0c;超时测试&#xff0c;参数化测试和依赖测试。 除了单元测试&#xff0c;TestNG的强大功能让他在接口和UI自动化中也占有…

UE4 Cesium 学习笔记

Cesium中CesiumGeoreference的原点Orgin&#xff0c;设置到新的位置上过后&#xff0c;将FloatingPawn的Translation全改为0&#xff0c;才能到对应的目标点上去 在该位置可以修改整体建筑的材质 防止刚运行的时候&#xff0c;人物就掉下场景之下&#xff0c;controller控制的…

导出LLaMA等LLM模型为onnx

通过onnx模型可以在支持onnx推理的推理引擎上进行推理&#xff0c;从而可以将LLM部署在更加广泛的平台上面。此外还可以具有避免pytorch依赖&#xff0c;获得更好的性能等优势。 这篇博客&#xff08;大模型LLaMa及周边项目&#xff08;二&#xff09; - 知乎&#xff09;进行…

堆的模板:使用一维数组实现小根堆,实现删除操作和堆顶元素输出功能

一、链接 838. 堆排序 二、题目 输入一个长度为 nn 的整数数列&#xff0c;从小到大输出前 mm 小的数。 输入格式 第一行包含整数 nn 和 mm。 第二行包含 nn 个整数&#xff0c;表示整数数列。 输出格式 共一行&#xff0c;包含 mm 个整数&#xff0c;表示整数数列中前…

外国(境外)机构在中国境内提供金融信息服务许可8家名单

6月30日&#xff0c;国家互联网信息办公室公布8家外国&#xff08;境外&#xff09;机构在中国境内提供金融信息服务许可名单&#xff0c;如下&#xff1a;

【云原生】使用kubeadm搭建K8S

目录 一、Kubeadm搭建K8S1.1环境准备1.2所有节点安装docker1.3所有节点安装kubeadm&#xff0c;kubelet和kubectl1.4部署K8S集群1.5所有节点部署网络插件flannel 二、部署 Dashboard 一、Kubeadm搭建K8S 1.1环境准备 服务器IP配置master&#xff08;2C/4G&#xff0c;cpu核心…

开源元数据管理平台Datahub最新版本0.10.5——安装部署手册(附离线安装包)

大家好&#xff0c;我是独孤风。 开源元数据管理平台Datahub近期得到了飞速的发展。已经更新到了0.10.5的版本&#xff0c;来咨询我的小伙伴也越来越多&#xff0c;特别是安装过程有很多问题。本文经过和群里大伙伴的共同讨论&#xff0c;总结出安装部署Datahub最新版本的部署手…

【Vue】Parsing error: No Babel config file detected for ... vue

报错 Parsing error: No Babel config file detected for E:\Study\Vue网站\实现防篡改的水印\demo02\src\App.vue. Either disable config file checking with requireConfigFile: false, or configure Babel so that it can find the config files.             …

fishing之第三篇邮件服务器搭建

文章目录 EwoMail 邮件服务器搭建一、前期准备二、安装EwoMail三、添加解析四、ewomail的后台管理系统五、WebMail(web邮件系统)六、收发邮件测试免责声明EwoMail 邮件服务器搭建 一、前期准备 1、云服务-CentOS服务器 2、购买域名 CentOS服务器43.x.x.x.域名abcxxx.xxx.c…

Vue day01

Vue 1.简介&#xff1a; ​ Vue是一套用于构建用户界面的渐进式框架。与其他大型框架不同的是&#xff0c;Vue被设计为可以自底向上逐层应用。Vue的核心库只关注视图层&#xff0c;不仅容易上手&#xff0c;还便于与第三方库或既有项目整合。另一方面&#xff0c;当与现代化的工…

MySQL — 存储引擎

文章目录 存储引擎存储引擎类型InnoDBMyISAMMEMORY 存储引擎是数据库的核心&#xff0c;对于mysql来说&#xff0c;存储引擎是以插件的形式运行的。虽然mysql支持种类繁多的存储引擎&#xff0c;但是常用的就那么几种。这篇文章主要是对其进行简单的介绍。 存储引擎 MySQL可插…

20天学会rust(一)和rust say hi

关注我&#xff0c;学习Rust不迷路 工欲善其事&#xff0c;必先利其器。第一节我们先来配置rust需要的环境和安装趁手的工具&#xff0c;然后写一个简单的小程序。 安装 Rust环境 Rust 官方有提供一个叫做 rustup 的工具&#xff0c;专门用于 rust 版本的管理&#xff0c;网…

xcode 的app工程与ffmpeg 4.4版本的静态库联调,ffmpeg内下的断点无法暂停。

先阐述一下我的业务场景&#xff0c;我有一个iOS的app sdk项目&#xff0c;下面简称 A &#xff0c;以及运行 A 的 app 项目&#xff0c;简称 A demo 。 引用关系为 A demo 引用了 A &#xff0c;而 A 引用了 ffmpeg 的静态库&#xff08;.a文件&#xff09;。此时业务出现了 b…

jmeter中json提取器,获取多个值,并通过beanshell组成数组

jmeter中json提取器介绍 特别说明&#xff1a;**Compute concatenation var(suffix_ALL)&#x1f617;*如果找到许多结果&#xff0c;则插件将使用’ &#xff0c; 分隔符将它们连接起来&#xff0c;并将其存储在名为 _ALL的var中 json提取器调试 在查看结果树中选择JSON Pat…

2023,谁在引领实时互动进入高清时代?

实践是检验真理的唯一标准&#xff0c;技术是行业进步的核心动能。在实时互动的新时代里&#xff0c;不断进化的声网已然完成自证。 作者|斗斗 出品|产业家 “一个医疗行业的客户&#xff0c;曾向我们提出一个需求&#xff0c;希望在120急救场景下&#xff0c;可以远程看清…

docker search 镜像报错: connect: no route to host (桥接模式配置静态IP)

如下 原因 可能有多种&#xff1a; ① 没有开放防火墙端口 ② ip地址配置有误 解决 我是因为虚拟机采用了桥接模式&#xff0c;配置静态ip地址有问题。 先确认虚拟机采用的是 桥接模式&#xff0c;然后启动虚拟机。 1、打开命令行&#xff0c;输入下面指令&#xff0c;打开…

[论文笔记] chatgpt系列 2.6 DeepSpeed-chat 数据集

一、FT数据集 & Reward model数据集 Deepspeed-chat 源代码的数据集: Dahoas/rm-static: 这是一个用于强化学习的静态环境数据集,包含了一个机器人在一个固定环境中的运动轨迹。该数据集旨在用于评估强化学习算法在静态环境下的表现。 Dahoas/full-hh-rlhf: 这是一个用于…