深入理解Redis 底层数据结构之QuickList与 ZipList

本文深入探讨Redis中的三种列表数据结构:链表(LinkedList)、压缩列表(ZipList)和快速列表(QuickList)。分析了每种数据结构的特点、应用场景以及转换条件,并提供了实际操作示例。
深入理解Redis 底层数据结构之QuickList 与ZipList

centos7安装redis6.25结合docker镜像配置方法(附redis.conf文件)

list底层的数据结构:

  1. linkedList 链表

  2. zipList 压缩列表

  3. quickList 快链表

在3,2版本之前,列表是通过双向链表或压缩链表来实现的。他们之间可以互相转换,在3.2版本之后又新加入了新的数据结构:QuickList,也就是双向链表和压缩列表的结合。

链表:LinkedList
image-20210920100036234
  • 数据结构中常用的带头节点的双向链表,并且带有指向头节点的头指针和指向最后一个节点的尾指针,双向链表保证从任意一个位置可以向前或者向后进行遍历,但要注意头节点的前指针为null,尾节点的后指针为空,这也就说明了redis中的LinkedList数据结构是一个无环链表,不支持逆序遍历

  • 第二点就是说,操作命令中的lpush(left push) 、lpop(left pop )等命令中的left代表从队头进行操作,right代表从队尾进行操作

  • 结构中的 len 字段记录了整个链表的长度。

  • 由于链表本身的特性,对链表进行增删操作所需的时间非常少,时间复杂度仅为O(1);但如果是需要凭借索引寻找链表中某个值,时间花销就显得有些高,时间复杂度为O(n)

  • dup函数用于对某个链节点进行复制操作

  • free函数用于对某个链节点进行释放操作,也就是删除

  • match函数用于判断某个链节点的值和输入的值是否相等。


压缩列表:ZipList
image-20210920120409330
  • redis中的压缩列表是用字节数组作为其数据结构。
  • 在zipList的数据结构中有以下字段:
    • zlbytes:整个压缩列表所占用的字节数,本身是4个字节即32位,因此压缩链表的最大长度为(2^32-1)个字节
    • zltail_offset:压缩列表尾部的元素到起始地址的偏移量,可以直接找到表尾元素,即支持逆序遍历
    • zlength:表中元素的个数,占2字节,如果列表中的元素个数超过(2^16-1)个,那么需要遍历整个列表才能得到元素的个数
    • entry:列表中存储的元素,可能是整数,也可能是字节数组,具体结果见下图
    • zlend:元素的结束标志,占一个字节,是一个常量OXFF
image-20210920122206052
  • entry保存中列表中的元素,可能是整数,也可能是字节数组。其结构体有三个字段:

    • pre_length:上一个元素的长度,方便逆序遍历的时候直接找到上个节点的起始位置。当前一个元素的长度小于254个字节的时候,用一个字节表示;当前一个元素的长度大于等于254个字节的时候,用5个字节表示,此时前一个字节存储固定值254

    • encoding: 长度为两个 bit 。 它的值可以是 00 、 01 、 10 和 11 。00 、 01 和 10表示 content 部分保存着字符数组,11表示 content 部分保存着整数。

    • content:保存真正的元素。

转换条件:
创建一个列表是,默认使用的数据结构是zipList,但在满足以下条件的时候,zipList会自动转化为双向链表:

  1. 压缩列表中插入了一个过长的字符串(长度可配置,默认65)
  2. 压缩列表中的节点数超过某一数量(默认512)

总结

  1. 当存储的元素很少的时候,通常采用zipList作为基础数据结构,而当数据元素较多时则采用LinkedList。

  2. 从数据结构本身的特点而言:LinkedList在插入和删除元素方面具有很大的优势。但其需要额外存储两个指针,存储开销比较大,而且每个元素都是单独的内存空间,地址不连续,容易造成内存碎片。

  3. 而压缩列表存储在一块连续的内存空间中,但是增加删除元素开销较大,在内存扩容执行realloc操作的时候需要进行大量的拷贝操作

快速列表:QuickList
image-20210920130149269

​ redis3.2之后,增加了新的数据结构:QuickList。它结合了LinkedList和zipList的优点。它将LinkedList的每个节点都用zipList的方式来存储。LinkedList节点之间依然采用双向链表连接起来,只

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值