当前位置:   article > 正文

内存节省到极致!Redis中的压缩表,值得了解_redis 压缩

redis 压缩

数据节点包括三个部分,分别是前一个节点的长度prev_entry_len,当前数据类型和编码格式encoding,具体数据指针value。

内存节省到极致!Redis中的压缩表,值得了解..

  • 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,这句话说明这并不是数据的实际存储格式。

是不是有点逗,定义了却没使用。

内存节省到极致!Redis中的压缩表,值得了解..

因为,这个结构存储实在是太浪费空间了。这个结构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表示字符串),现在想要把第二个数据的改大点,哪个时候就会发生级联更新了。

内存节省到极致!Redis中的压缩表,值得了解..

步骤二

===

我们想要分配四个长度的大小给第三个数据的prevlen,因为第二个元素的prevlen字段是表示他前一个元素的大小。

内存节省到极致!Redis中的压缩表,值得了解..

步骤三

===

调整完发现第三个元素的长度增加了,所以第四个元素的prevlen字段也需要修改。

内存节省到极致!Redis中的压缩表,值得了解..

步骤四

===

调整完发现第四个元素的长度增加了,所以把第五个元素的prevlen字段也需要修改。

压缩列表的源码分析

=========

创建空的压缩表ziplistNew

=================

主要的步骤是分配内存空间,初始化属性,设置结束标记为常量,最后返回压缩表。

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
img

最后

小编在这里分享些我自己平时的学习资料,由于篇幅限制,pdf文档的详解资料太全面,细节内容实在太多啦,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!

开源分享:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】

程序员代码面试指南 IT名企算法与数据结构题目最优解

这是” 本程序员面试宝典!书中对IT名企代码面试各类题目的最优解进行了总结,并提供了相关代码实现。针对当前程序员面试缺乏权威题目汇总这一-痛点, 本书选取将近200道真实出现过的经典代码面试题,帮助广“大程序员的面试准备做到万无一失。 “刷”完本书后,你就是“题王”!

image.png

《TCP-IP协议组(第4版)》

本书是介绍TCP/IP协议族的经典图书的最新版本。本书自第1版出版以来,就广受读者欢迎。

本书最新版进行」护元,以体境计算机网络技不的最新发展,全书古有七大部分共30草和7个附录:第一部分介绍一些基本概念和基础底层技术:第二部分介绍网络层协议:第三部分介绍运输层协议;第四部分介绍应用层协议:第五部分介绍下一代协议,即IPv6协议:第六部分介绍网络安全问题:第七部分给出了7个附录。

image.png

Java开发手册(嵩山版)

这个不用多说了,阿里的开发手册,每次更新我都会看,这是8月初最新更新的**(嵩山版)**

image.png

MySQL 8从入门到精通

本书主要内容包括MySQL的安装与配置、数据库的创建、数据表的创建、数据类型和运算符、MySQL 函数、查询数据、数据表的操作(插入、更新与删除数据)、索引、存储过程和函数、视图、触发器、用户管理、数据备份与还原、MySQL 日志、性能优化、MySQL Repl ication、MySQL Workbench、 MySQL Utilities、 MySQL Proxy、PHP操作MySQL数据库和PDO数据库抽象类库等。最后通过3个综合案例的数据库设计,进步讲述 MySQL在实际工作中的应用。

image.png

Spring5高级编程(第5版)

本书涵盖Spring 5的所有内容,如果想要充分利用这一领先的企业级 Java应用程序开发框架的强大功能,本书是最全面的Spring参考和实用指南。

本书第5版涵盖核心的Spring及其与其他领先的Java技术(比如Hibemate JPA 2.Tls、Thymeleaf和WebSocket)的集成。本书的重点是介绍如何使用Java配置类、lambda 表达式、Spring Boot以及反应式编程。同时,将与企业级应用程序开发人员分享一些见解和实际经验,包括远程处理、事务、Web 和表示层,等等。

image.png

JAVA核心知识点+1000道 互联网Java工程师面试题

image.png

image.png

企业IT架构转型之道 阿里巴巴中台战略思想与架构实战

本书讲述了阿里巴巴的技术发展史,同时也是-部互联网技 术架构的实践与发展史。

image.png

人员分享一些见解和实际经验,包括远程处理、事务、Web 和表示层,等等。

[外链图片转存中…(img-mbHg1j4E-1710750747900)]

JAVA核心知识点+1000道 互联网Java工程师面试题

[外链图片转存中…(img-7jvXKtem-1710750747900)]

[外链图片转存中…(img-V4J9l3PW-1710750747900)]

企业IT架构转型之道 阿里巴巴中台战略思想与架构实战

本书讲述了阿里巴巴的技术发展史,同时也是-部互联网技 术架构的实践与发展史。

[外链图片转存中…(img-trEhBTdE-1710750747900)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/538585
推荐阅读
相关标签
  

闽ICP备14008679号