redis数据结构源码分析——压缩列表ziplist(I)

前面讲了跳表的源码分析,本篇我们来聊一聊另外一个重点结构——压缩列表

存储结构

字节数组结构

压缩列表就是一个字节数组(char *zl)
有序集合、散列和列表都直接或间接使用到压缩列表
在这里插入图片描述
zlbytes:压缩列表的字节长度
zltail:压缩列表尾元素相对于压缩列表起始地址的偏移量
zllen:压缩列表的元素个数
entry:各个节点
zlend:压缩列表的结尾,占一个字节,一直是0xFF(255)

节点结构

也就是entry里存的是什么
在这里插入图片描述
网上很多这样的图,那么这个结构是哪里来的呢?我们看下源码中的注释:
在这里插入图片描述
prevlen:前一个元素的字节长度
encoding:当前元素的编码,占一个字节,八位。前两位存的是元数据的类型,后六位存的是元数据的长度
entry-data:元数据,也就是当前的内容
prevlen和encoding这两部分是作为元数据的前缀信息。注意!这里的注释说了,通常情况下是这样的结构,但也有其他情况:
在这里插入图片描述
有时候encoding代表entry本身,比如说小整数(0-12),在这种情况下,是没有entry-data的
这里的注释能看出来编码的实际样式,简单翻译一下:

压缩编码

zipEntry

zlEntry

zipEntry解压完后是zlEntry
在这里插入图片描述
prevrawlensize:存储prevrawlen需要的字节数
prevrawlen:前一个节点占用的字节数
lensize:存储len需要的字节数
len:数据长度
headersize:首部长度,等于prevrawlensize + lensize
encoding:当前元素编码
*p:当前元素首地址

ZIP_DECODE_PREVLEN

用来解码prevlen字段
根据注释我们可以了解prevlen
在这里插入图片描述
我们大概翻译一下这里的注释:如果prevlen长度小于254字节,就只消耗单个将长度表示为无符号8位整数的字节。当长度大于或等于254,则它将消耗5个字节。第一个字节是设置为254(FE)以指示后面是更大的值。剩下的4个字节将上一个条目的长度作为值。
我们看下代码:
在这里插入图片描述
其实从这里可以看出,这个值要么是1要么是5.
大概流程可以这样表示:
在这里插入图片描述

ZIP_DECODE_LENGTH

用来解码encoding字段
在这里插入图片描述
这里的代码比较长,但是能看出来,就是根据传入的当前元素和encoding求len和lensize

API解析

这里我们大概讲下以下四个API,后三个插入删除和查找的源码较长,我们本篇只做大概讲解,详细的讲解在这里:redis源码解析——压缩列表ziplist(II)API详解+级联更新

ziplistNew(创建压缩列表)

在这里插入图片描述
这块是比较简单的,大概步骤如下:
1、计算长度
2、根据计算出的长度申请内存(zmalloc方法)
3、各个字段赋初始值
4、返回字节数组的地址
这里的zmalloc方法就是分配内存作用
在这里插入图片描述

ziplistInsert(插入)

在这里插入图片描述
这里的__ziplistInsert方法比较复杂,我们后续可以专门出一篇文章讲解下,这里就做个步骤的大概梳理:
1、编码
2、重新分配空间
3、数据复制

ziplistDelete(删除)

在这里插入图片描述
这里相对于插入来说是比较简单的,不过详细源码解析我们跟插入流程一起出一篇讲解,这里的大概流程为:
1、先计算出要删除的元素的长度
2、数据复制
3、重新分配空间

ziplistFind(查找)

1、计算节点属性
2、判断节点类型
3、如果是字符串,对比内容
4、如果是整数,对比数值
5、找到就返回,找不到就指向下一个

压缩列表的设计思想和优势

设计思想

1、为了节省空间而设计
2、内存是连续的,元素之间没有空隙
3、encoding不仅存类型,也可以存长度
4、不存储前后节点的指针,并不是通过索引来找位置,而是通过长度计算前后节点的位置
5、zlentry的解码存储

优势

1、节省内存,其实也就是以时间换空间。相对来说更适用于比较小的数据或是说比较少的数据量大场景
2、zlentry可以提供快速访问

2023过去了,祝愿各位朋友们2024龙年大吉,技术越来越好,也希望自己在新的一年里技术提升,工作顺利。最近写redis的源码系列看了不少文章,这里给大家提个建议,看到网上的文章或教学时,不要完全的跟着教学走,比如这里的entry结构,一定要带着怀疑的态度自己去翻翻源码,我原本也是看到网上的文章,但是看到entry结构时,看了很多文章都是过于八股,没有一篇文章讲的是明白的,所以还是建议大家带着怀疑的心态学习。
最后,有任何疑问或不同意见,欢迎留言讨论。

  • 18
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值