赞
踩
数据节点包括三个部分,分别是前一个节点的长度prev_entry_len,当前数据类型和编码格式encoding,具体数据指针value。
prev_entry_len:记录前驱节点的长度。
encoding:记录当前数据类型和编码格式。
value:存放具体的数据。
压缩列表的具体实现
=========
压缩列表的构成
=======
Redis并没有像之前的字符串SDS,字典,跳跃表等结构一样,封装一个结构体来保存压缩列表的信息。而是通过定义一系列宏来对数据进行操作。
也就是说压缩列表是一堆字节码,咱也看不懂,Redis通过字节之间的定位和计算来获取数据的。
//返回整个压缩列表的总字节
#define ZIPLIST_BYTES(zl) (((uint32_t)(zl)))
//返回压缩列表的tail_offset变量,方便获取最后一个节点的位置
#define ZIPLIST_TAIL_OFFSET(zl) (((uint32_t)((zl)+sizeof(uint32_t))))
//返回压缩列表的节点数量
#define ZIPLIST_LENGTH(zl) (((uint16_t)((zl)+sizeof(uint32_t)*2)))
//返回压缩列表的表头的字节数
//(内存字节数zlbytes,最后一个节点地址ztail_offset,节点总数量zllength)
#define ZIPLIST_HEADER_SIZE (sizeof(uint32_t)*2+sizeof(uint16_t))
//返回压缩列表最后结尾的字节数
#define ZIPLIST_END_SIZE (sizeof(uint8_t))
//返回压缩列表首节点地址
#define ZIPLIST_ENTRY_HEAD(zl) ((zl)+ZIPLIST_HEADER_SIZE)
//返回压缩列表尾节点地址
#define ZIPLIST_ENTRY_TAIL(zl) ((zl)+intrev32ifbe(ZIPLIST_TAIL_OFFSET(zl)))
//返回压缩列表最后结尾的地址
#define ZIPLIST_ENTRY_END(zl) ((zl)+intrev32ifbe(ZIPLIST_BYTES(zl))-1)
压缩列表节点的构成
=========
我们看下面的代码,重点看注释,Note that this is not how the data is actually encoded,这句话说明这并不是数据的实际存储格式。
是不是有点逗,定义了却没使用。
因为,这个结构存储实在是太浪费空间了。这个结构32位机占用了25(int类型5个,每个int占4个字节,char类型1个,每个char占用1个字节,char*类型1个,每个char*占用4个字节,所以总共5*4+1*1+1*4=25)个字节,在64位机占用了29(int类型5个,每个int占4个字节,char类型1个,每个char占用1个字节,char*类型1个,每个char*占用8个字节,所以总共5*4+1*1+1*8=29个字节)。这不符合压缩列表的设计目的。
/* We use this function to receive information about a ziplist entry.
Note that this is not how the data is actually encoded, is just what we
get filled by a function in order to operate more easily. */
typedef struct zlentry {
unsigned int prevrawlensize; //记录prevrawlen需要的字节数
unsigned int prevrawlen; //记录上个节点的长度
unsigned int lensize; //记录len需要的字节数
unsigned int len; //记录节点长度
unsigned int headersize; //prevrawlensize+lensize
unsigned char encoding; //编码格式
unsigned char *p; //具体的数据指针
} zlentry;
所以Redis对上述结构进行了改进了,抽象合并了三个参数。
prev_entry_len:prevrawlensize和prevrawlen的总和。
如果前一个节点长度小于254字节,那么prev_entry_len使用一个字节表示。
如果前一个节点长度大于等于254字节,那么prev_entry_len使用五个字节表示。第一个字节为常数oxff,后面四位为真正的前一个节点的长度。
encoding:lensize和len的总和。Redis通过设置了一组宏定义,使其能够具有lensize和len两种功能。(具体即不展开了)
value:具体的数据。
压缩列表的优点
=======
压缩列表的缺点
=======
因为压缩表是紧凑存储的,没有多余的空间。这就意味着插入一个新的元素就需要调用函数扩展内存。过程中可能需要重新分配新的内存空间,并将之前的内容一次性拷贝到新的地址。
如果数据量太多,重新分配内存和拷贝数据会有很大的消耗。所以压缩表不适合存储大型字符串,并且数据元素不能太多。
压缩列表的连锁更新过程图解(重点)
=================
前面提到每个节点entry都会有一个prevlen字段存储前一个节点entry的长度,如果内容小于254,prevlen用一个字节存储,如果大于254,就用五个字节存储。这意味着如果某个entry经过操作从253字节变成了254字节,那么他的下一个节点entry的pervlen字段就要更新,从1个字节扩展到5个字节;如果这个entry的长度本来也是253字节,那么后面entry的prevlen字段还得继续更新。
如果每个节点entry都存储的253个字节的内容,那么第一个entry修改后会导致后续所有的entry的级联更新,这是一个比较损耗资源的操作。
所以,发生级联更新的前提是有连续的250-253字节长度的节点。
步骤一
===
比如一开始的压缩表呈现下图所示(XXXX表示字符串),现在想要把第二个数据的改大点,哪个时候就会发生级联更新了。
步骤二
===
我们想要分配四个长度的大小给第三个数据的prevlen,因为第二个元素的prevlen字段是表示他前一个元素的大小。
步骤三
===
调整完发现第三个元素的长度增加了,所以第四个元素的prevlen字段也需要修改。
步骤四
===
调整完发现第四个元素的长度增加了,所以把第五个元素的prevlen字段也需要修改。
压缩列表的源码分析
=========
创建空的压缩表ziplistNew
=================
主要的步骤是分配内存空间,初始化属性,设置结束标记为常量,最后返回压缩表。
小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
小编在这里分享些我自己平时的学习资料,由于篇幅限制,pdf文档的详解资料太全面,细节内容实在太多啦,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!
开源分享:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】
程序员代码面试指南 IT名企算法与数据结构题目最优解
这是” 本程序员面试宝典!书中对IT名企代码面试各类题目的最优解进行了总结,并提供了相关代码实现。针对当前程序员面试缺乏权威题目汇总这一-痛点, 本书选取将近200道真实出现过的经典代码面试题,帮助广“大程序员的面试准备做到万无一失。 “刷”完本书后,你就是“题王”!
《TCP-IP协议组(第4版)》
本书是介绍TCP/IP协议族的经典图书的最新版本。本书自第1版出版以来,就广受读者欢迎。
本书最新版进行」护元,以体境计算机网络技不的最新发展,全书古有七大部分共30草和7个附录:第一部分介绍一些基本概念和基础底层技术:第二部分介绍网络层协议:第三部分介绍运输层协议;第四部分介绍应用层协议:第五部分介绍下一代协议,即IPv6协议:第六部分介绍网络安全问题:第七部分给出了7个附录。
Java开发手册(嵩山版)
这个不用多说了,阿里的开发手册,每次更新我都会看,这是8月初最新更新的**(嵩山版)**
MySQL 8从入门到精通
本书主要内容包括MySQL的安装与配置、数据库的创建、数据表的创建、数据类型和运算符、MySQL 函数、查询数据、数据表的操作(插入、更新与删除数据)、索引、存储过程和函数、视图、触发器、用户管理、数据备份与还原、MySQL 日志、性能优化、MySQL Repl ication、MySQL Workbench、 MySQL Utilities、 MySQL Proxy、PHP操作MySQL数据库和PDO数据库抽象类库等。最后通过3个综合案例的数据库设计,进步讲述 MySQL在实际工作中的应用。
Spring5高级编程(第5版)
本书涵盖Spring 5的所有内容,如果想要充分利用这一领先的企业级 Java应用程序开发框架的强大功能,本书是最全面的Spring参考和实用指南。
本书第5版涵盖核心的Spring及其与其他领先的Java技术(比如Hibemate JPA 2.Tls、Thymeleaf和WebSocket)的集成。本书的重点是介绍如何使用Java配置类、lambda 表达式、Spring Boot以及反应式编程。同时,将与企业级应用程序开发人员分享一些见解和实际经验,包括远程处理、事务、Web 和表示层,等等。
JAVA核心知识点+1000道 互联网Java工程师面试题
企业IT架构转型之道 阿里巴巴中台战略思想与架构实战
本书讲述了阿里巴巴的技术发展史,同时也是-部互联网技 术架构的实践与发展史。
人员分享一些见解和实际经验,包括远程处理、事务、Web 和表示层,等等。
[外链图片转存中…(img-mbHg1j4E-1710750747900)]
JAVA核心知识点+1000道 互联网Java工程师面试题
[外链图片转存中…(img-7jvXKtem-1710750747900)]
[外链图片转存中…(img-V4J9l3PW-1710750747900)]
企业IT架构转型之道 阿里巴巴中台战略思想与架构实战
本书讲述了阿里巴巴的技术发展史,同时也是-部互联网技 术架构的实践与发展史。
[外链图片转存中…(img-trEhBTdE-1710750747900)]
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。