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

2024-02-26 10:28

本文主要是介绍redis数据结构源码分析——压缩列表ziplist(I),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

文章目录

  • 存储结构
    • 字节数组结构
    • 节点结构
  • 压缩编码
    • zipEntry
      • zlEntry
    • ZIP_DECODE_PREVLEN
    • ZIP_DECODE_LENGTH
  • API解析
    • ziplistNew(创建压缩列表)
    • ziplistInsert(插入)
    • ziplistDelete(删除)
    • ziplistFind(查找)
  • 压缩列表的设计思想和优势
    • 设计思想
    • 优势

存储结构

字节数组结构

压缩列表就是一个字节数组(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结构时,看了很多文章都是过于八股,没有一篇文章讲的是明白的,所以还是建议大家带着怀疑的心态学习。
最后,有任何疑问或不同意见,欢迎留言讨论。

这篇关于redis数据结构源码分析——压缩列表ziplist(I)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/748543

相关文章

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Linux中压缩、网络传输与系统监控工具的使用完整指南

《Linux中压缩、网络传输与系统监控工具的使用完整指南》在Linux系统管理中,压缩与传输工具是数据备份和远程协作的桥梁,而系统监控工具则是保障服务器稳定运行的眼睛,下面小编就来和大家详细介绍一下它... 目录引言一、压缩与解压:数据存储与传输的优化核心1. zip/unzip:通用压缩格式的便捷操作2.

Redis出现中文乱码的问题及解决

《Redis出现中文乱码的问题及解决》:本文主要介绍Redis出现中文乱码的问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 问题的产生2China编程. 问题的解决redihttp://www.chinasem.cns数据进制问题的解决中文乱码问题解决总结

MySQL中的表连接原理分析

《MySQL中的表连接原理分析》:本文主要介绍MySQL中的表连接原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、表连接原理【1】驱动表和被驱动表【2】内连接【3】外连接【4编程】嵌套循环连接【5】join buffer4、总结1、背景

python中Hash使用场景分析

《python中Hash使用场景分析》Python的hash()函数用于获取对象哈希值,常用于字典和集合,不可变类型可哈希,可变类型不可,常见算法包括除法、乘法、平方取中和随机数哈希,各有优缺点,需根... 目录python中的 Hash除法哈希算法乘法哈希算法平方取中法随机数哈希算法小结在Python中,

Java Stream的distinct去重原理分析

《JavaStream的distinct去重原理分析》Javastream中的distinct方法用于去除流中的重复元素,它返回一个包含过滤后唯一元素的新流,该方法会根据元素的hashcode和eq... 目录一、distinct 的基础用法与核心特性二、distinct 的底层实现原理1. 顺序流中的去重

Redis的持久化之RDB和AOF机制详解

《Redis的持久化之RDB和AOF机制详解》:本文主要介绍Redis的持久化之RDB和AOF机制,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录概述RDB(Redis Database)核心原理触发方式手动触发自动触发AOF(Append-Only File)核

Redis分片集群、数据读写规则问题小结

《Redis分片集群、数据读写规则问题小结》本文介绍了Redis分片集群的原理,通过数据分片和哈希槽机制解决单机内存限制与写瓶颈问题,实现分布式存储和高并发处理,但存在通信开销大、维护复杂及对事务支持... 目录一、分片集群解android决的问题二、分片集群图解 分片集群特征如何解决的上述问题?(与哨兵模

SpringBoot连接Redis集群教程

《SpringBoot连接Redis集群教程》:本文主要介绍SpringBoot连接Redis集群教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 依赖2. 修改配置文件3. 创建RedisClusterConfig4. 测试总结1. 依赖 <de

SpringBoot+Redis防止接口重复提交问题

《SpringBoot+Redis防止接口重复提交问题》:本文主要介绍SpringBoot+Redis防止接口重复提交问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不... 目录前言实现思路代码示例测试总结前言在项目的使用使用过程中,经常会出现某些操作在短时间内频繁提交。例