redis基础数据结构——ZipList

news/2025/3/26 12:55:56/文章来源:https://www.cnblogs.com/kun1790051360/p/18751257

ZipList

基于特殊写法实现的双端链表,由一系列特殊编码的连续内存块组成,可以像deque一样在双端压入/弹出,并且时间复杂度在O(1)

整体ZL结构如下

zlbytes(uint32):当前zl总的byte数。

zltail(uint32):尾结点的offset,指向的是最后一个entry的起始地址。

zllen(uint16):记录entry的个数。4字节最多能记录到UINT16_MAX(65534),后续超过这个值会被记录为65535,此时len就不再是真实节点数量。

zlend(uint8):特殊值,结束标示:0xff。

entry(zipListEntry):第一个entry称为头结点;最后一个entry称为尾结点。

 

ziplistentry内部存储格式

  • previous_entry_length:前一节点的长度,占1个或5个字节。
    • 前一节点长度如果小于254byte,则采用1字节保存其长度值
    • 前一节点长度如果大于254byte,则采用5字节保存其长度值,第一个字节为0xfe,后续才是真实长度数据
  • encoding:编码属性,记录content数据类型与长度,可能占1/2/5个字节
  • contents:就是data,可能是字符串或整数

zl是在内存中一块连续的存储空间,并且基于上述结构实现了特殊的双端链表

  • 后驱的情况下,我们可以根据当前entry的总长度推出下一个entry的起始地址;
  • 前驱的情况下,我们可以通过previous_entry_length获取上一节点的位置。

此外zl会根据编码来存储字符串/整数。

encoding以00,01,10开头时说明存储的是字符串,并且根据其二进制大小来确认字符串长度大小

encoding以11开头说明存储的是整数,并且特别优化的一点是:当整数太小(大概是0~12),content直接存放在encoding即可,不需要再浪费额外空间

 

问题:当链表过于冗长的时候,查询的性能会很差(因为只能从头到尾遍历或者从尾向头遍历),因此使用zl时需要控制其len的大小

 

ziplistEntry外部接口

typedef struct {unsigned char *sval;  // 指向字符串值的指针unsigned int slen;    // 字符串的长度long long lval;       // 整数值(当条目是整数时使用)
} ziplistEntry;

这是redis内提供给外部使用的ziplistEntry源码。这个结构体让使用者不需要具体关心zl的内部实现,即可方便调用,是一种解耦思想。

 

zipList连锁更新问题(作者也没解决)

zipList中每个entry都包含了一个previous_entry_length用于记录上一个节点大小。(规则在内部存储格式)

:假设有连续多个长度为250~252字节长度的entry,此时每一个previous_entry_length都只用1个字节存储。

    但如果头插了一个长度大于等于254字节的entry,会导致原本长度在250~252字节长度的entry需要修改pre_entry_length(由原本的1字节存储变为5字节存储,这会导致entry整体大小超过254)。

    而多个长度擦边的entry,会不断向后申请空间

虽然没有解决,但是后续作者提出来用listPack(redis5.0+)替换zipList,但是由于改动过大,并且出现问题概率太小,作者也只是在stream里使用了listPack,正常情况下list、set等还是基于zipList的

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

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

相关文章

day:28 postman——环境变量(依赖,关联接口)

一.接口的环境变量 (1)定义变量 可以将需要填写的值设为变量 变量设置:{{}}(2)添加环境变量 方法一:方法二:(3)查看环境变量(4)选择环境,执行二.依赖接口 先登录接口成功,生成cookie值,才能让后面接口依赖 cookie值是保持会话 查看cookie值方法 方法一:方法二:…

L1.1 技术和产品准备度

L1.1 技术和产品准备度 技术和产品准备度 技术与产品的演进 ​ 上面这张图展示了如何在技术尚未完全成熟时,启动产品开发,以及技术如何随着新需求或洞察逐步演进,并支持产品的更新换代。产品1.0:由先前研发的的技术3支撑,加上“产品开发可以在预期的技术开发成果的基础上提…

从故障响应到客户信赖:华为ITR流程的五大核心步骤与实战案例

华为究竟是如何在与西方巨头的激烈竞争中崭露头角、脱颖而出的呢?答案是:凭借卓越的服务。今天我们来探讨一下华为是如何通过卓越的服务赢得全球市场的。 一、华为的三件大事 华为前高管费敏曾经总结过,华为的业务可以分成三件大事:1. 开发产品:这就是 IPD 流程,负责从有…

提升生产效率的关键: ethercat转TCPIP智能通信

大家好。最近在数据互联互通方面,我们迎来了一个重要的突破。作为生产管理系统的核心组成部分,数据互联互通一直是一个亟待解决的挑战。我们知道,EtherCAT和TCP/IP是两种不同的通信协议,它们之间的互通性一直存在问题。不过,现在有一款新产品值得关注,这款产品能够实现Et…

Trae初体验

Trae(国际版)的Ai搭载Claude-3.7-Sonnet(完全免费且速度很快)和DeepSeek-R1以及V3(不存在服务器繁忙)以及GPT-4o Trae国服的Ai搭载DouBao和DeepSeek。用Claude-3.7-Sonnet 写一个简易的贪吃蛇小游戏:这个贪吃蛇游戏包含以下功能:使用方向键控制蛇的移动 吃到食物会增加长度和…

C# 从零开始使用Layui.Wpf库开发WPF客户端

一、简介最近需要开发一个桌面版的工具软件,之前用得更多的是Winform,作为一个全干工程师,我们也要兼顾下WPF,趁此机会再研究下开源控件库。MaQaQ:Winform真好用(有个HZHControls控件库,值得一看)。 二、准备工作找了下开源控件库,诸如MaterialDesignInXAML、HandyCon…

聚点和闭包中点的等价条件

聚点有以下等价描述: 闭包中点有以下等价描述:这些等价描述在与导集和闭包的证明中能起到很大的作用。下面是一个例子。

Itext5生成高质量、易识别、适合小尺寸标签打印的二维码

高质量、易识别、小尺寸二维码生成 1.增大二维码的原始尺寸(例如 1000 x 1000 或更大),再缩放为 PDF 所需的大小。这样可以保留更多像素细节,提高识别率。 2.降低容错级别到 L 或 M,如果你的内容不是特别长或复杂的话,这样能减少密集度。 3.优化缩放方式: • 使用 Buffe…

【Docker】安装部署jenkins

docker安装部署jenkinsdocker安装jenkins  1、下载jenkins  2、创建挂载目录  3、启动jenkins容器  4、验证jenkins是否启动成功  5、获取管理员密码  6、下载安装插件 docker安装jenkins【1】下载jenkins拉取jenkins镜像 docker pull jenkins/jenkins:2.426.2-lts…

焊接保护气体智能调节控制器|节气装置

机器人焊接节气装置在焊接流程中扮演着至关重要的角色,它犹如一道坚实的屏障,为熔融金属营造一个纯净的焊接环境,有效抵御空气中氧气、氮气、水蒸气等不良因素的侵扰。具体而言,保护气体的多重功效可详尽阐述为以下几个层面:对焊缝的精心呵护。在诸如氩弧焊等精密焊接工艺…

线段树+扫描线,解决“静态矩阵加和+矩阵查询”问题

在试图用 CDQ 分治做这道题的时候遇到了一些麻烦,修改全部在查询之前的静态部分不会做,题解虽然还算详细,但是本人蒟蒻仍然无法理解,思考一上午,尝试过各种证明方法后,大致证明题解算法的正确性,记录在这里。先看题解的说法和代码:使用扫描线、线段树和差分离线解决静态…