快速列表

  • 一. 基本结构
    • ①. ziplist 和 linkedlist介绍
    • ②. quicklistNode 基本结构
    • ②. quicklistLZF 结构
    • ③. quicklist 结构
    • ④. 插入
    • ⑤. 查找
    • ⑥. 删除

一. 基本结构

①. ziplist 和 linkedlist介绍

  • Redis3.2版本开始对列表数据结构进行了改造,使用 quicklist 代替了 ziplist 和 linkedlist.

②. quicklistNode 基本结构

typedef struct quicklistNode {struct quicklistNode *prev; //上一个node节点struct quicklistNode *next; //下一个nodeunsigned char *zl;            //保存的数据 压缩前ziplist 压缩后压缩的数据unsigned int sz;             /* ziplist size in bytes */unsigned int count : 16;     /* count of items in ziplist */unsigned int encoding : 2;   /* RAW==1 or LZF==2 */unsigned int container : 2;  /* NONE==1 or ZIPLIST==2 */unsigned int recompress : 1; /* was this node previous compressed? */unsigned int attempted_compress : 1; /* node can't compress; too small */unsigned int extra : 10; /* more bits to steal for future usage */
} quicklistNode;
  • prev: 指向链表前一个节点的指针。
  • next: 指向链表后一个节点的指针。
  • zl: 数据指针。如果当前节点的数据没有压缩,那么它指向一个ziplist结构;否则,它指向一个quicklistLZF结构。
  • sz: 表示zl指向的ziplist的总大小(包括zlbytes, zltail, zllen, zlend和各个数据项)。需要注意的是:如果ziplist被压缩了,那么这个sz的值仍然是压缩前的ziplist大小。
  • count: 表示ziplist里面包含的数据项个数。这个字段只有16bit。稍后我们会一起计算一下这16bit是否够用。
  • encoding: 表示ziplist是否压缩了(以及用了哪个压缩算法)。目前只有两种取值:2表示被压缩了(而且用的是LZF压缩算法),1表示没有压缩。
  • container: 是一个预留字段。本来设计是用来表明一个quicklist节点下面是直接存数据,还是使用ziplist存数据,或者用其它的结构来存数据(用作一个数据容器,所以叫container)。但是,在目前的实现中,这个值是一个固定的值2,表示使用ziplist作为数据容器。
  • recompress: 当我们使用类似lindex这样的命令查看了某一项本来压缩的数据时,需要把数据暂时解压,这时就设置recompress=1做一个标记,等有机会再把数据重新压缩。
  • attempted_compress: 这个值只对Redis的自动化测试程序有用。我们不用管它。
  • extra: 其它扩展字段。目前Redis的实现里也没用上。

②. quicklistLZF 结构

typedef struct quicklistLZF {unsigned int sz; /* LZF size in bytes*/char compressed[];
} quicklistLZF;
  • quicklistLZF结构表示一个被压缩过的ziplist。其中:

  • sz: 表示压缩后的ziplist大小。

  • compressed: 是个柔性数组(flexible array member),存放压缩后的ziplist字节数组。

③. quicklist 结构

typedef struct quicklist {quicklistNode *head;quicklistNode *tail;unsigned long count;        /* total count of all entries in all ziplists */unsigned long len;          /* number of quicklistNodes */int fill : QL_FILL_BITS;              /* fill factor for individual nodes */unsigned int compress : QL_COMP_BITS; /* depth of end nodes not to compress;0=off */unsigned int bookmark_count: QL_BM_BITS;quicklistBookmark bookmarks[];
} quicklist;
  • head: 指向头节点(左侧第一个节点)的指针。
  • tail: 指向尾节点(右侧第一个节点)的指针。
  • count: 所有ziplist数据项的个数总和。
  • len: quicklist节点的个数。
  • fill: 16bit,ziplist大小设置,存放list-max-ziplist-size参数的值。
  • compress: 16bit,节点压缩深度设置,存放list-compress-depth参数的值。

④. 插入

  • quicklist可以选择在头部或者尾部进行插入(quicklistPushHead和quicklistPushTail),而不管是在头部还是尾部插入数据,都包含两种情况:

    • 如果头节点(或尾节点)上ziplist大小没有超过限制(即_quicklistNodeAllowInsert返回1),那么新数据被直接插入到ziplist中(调用ziplistPush)。
    • 如果头节点(或尾节点)上ziplist太大了,那么新创建一个quicklistNode节点(对应地也会新创建一个ziplist),然后把这个新创建的节点插入到quicklist双向链表中。

  • 也可以从任意指定的位置插入。quicklistInsertAfter和quicklistInsertBefore就是分别在指定位置后面和前面插入数据项。这种在任意指定位置插入数据的操作,要比在头部和尾部的进行插入要复杂一些。

    • 当插入位置所在的ziplist大小没有超过限制时,直接插入到ziplist中就好了;
    • 当插入位置所在的ziplist大小超过了限制,但插入的位置位于ziplist两端,并且相邻的quicklist链表节点的ziplist大小没有超过限制,那么就转而插入到相邻的那个quicklist链表节点的ziplist中;
    • 当插入位置所在的ziplist大小超过了限制,但插入的位置位于ziplist两端,并且相邻的quicklist链表节点的ziplist大小也超过限制,这时需要新创建一个quicklist链表节点插入。
    • 对于插入位置所在的ziplist大小超过了限制的其它情况(主要对应于在ziplist中间插入数据的情况),则需要把当前ziplist分裂为两个节点,然后再其中一个节点上插入数据。

⑤. 查找

  • list的查找操作主要是对index的我们的quicklist的节点是由一个一个的ziplist构成的每个ziplist都有大小。所以我们就只需要先根据我们每个node的个数,从而找到对应的ziplist,调用ziplist的index就能成功找到。

⑥. 删除

  • 区间元素删除的函数是 quicklistDelRange

  • quicklist 在区间删除时,会先找到 start 所在的 quicklistNode,计算删除的元素是否小于要删除的 count,如果不满足删除的个数,则会移动至下一个 quicklistNode 继续删除,依次循环直到删除完成为止。

  • quicklistDelRange 函数的返回值为 int 类型,当返回 1 时表示成功的删除了指定区间的元素,返回 0 时表示没有删除任何元素。

Redis的底层数据结构----快速列表_quicklist相关推荐

  1. Redis专题-底层数据结构与使用场景

    Redis介绍 Redis是一种基于键值对的NoSQL数据库,是一个基于内存中的数据结构存储系统,可以用作数据库.缓存和消息中间件.它支持以string(字符串),hash(哈希),list(列表), ...

  2. redis:redis的底层数据结构

    高效的数据结构 redis中的数据结构有2种意思: (redis本质上是一个hashmap) redis键值对中的值的数据类型,也就是数据的保存形式,常用的有5种:String(字符串).List(列 ...

  3. redis 底层数据结构 压缩列表 ziplist

    压缩列表是列表键和哈希键的底层实现之一.当一个列表键只包含少量列表项,并且每个列表项要么就是小整数,要么就是长度比较短的字符串,redis就会使用压缩列表来做列表键的底层实现 当一个哈希键只包含少量键 ...

  4. 四、redis的底层数据结构

    1.演示数据类型的实现 上篇博客我们在介绍 key 相关命令的时候,介绍了如下命令: OBJECT ENCODING key 该命令是用来显示那五大数据类型的底层数据结构. 比如对于 string 数 ...

  5. c++ map底层_Redis详解(四)------ redis的底层数据结构

    > 本系列教程持续更新,可以微信搜索「 IT可乐 」第一时间阅读.回复<电子书>有我为大家特别筛选的书籍资料 上一篇博客我们介绍了 redis的五大数据类型详细用法,但是在 Redi ...

  6. Redis六种底层数据结构

    文章目录 一.简单动态字符串 1.SDS的结构定义 2.SDS和c字符串的区别 1)SDS获取字符串长度复杂度为常数 2)SDS杜绝了缓冲区溢出 3)减少内存重分配次数 4)二进制安全 5)SDS兼容 ...

  7. 图解 Redis String 底层数据结构 SDS 与计数器实战

    我是 Redis,给开发者提供了 String(字符串).Hashes(散列表).Lists(列表).Sets(无序集合).Sorted Sets(可根据范围查询的排序集合).Bitmap(位图).H ...

  8. Redis zset 底层数据结构之跳表

    参考: redis zset 内部的实现原理_行走在江湖的博客-CSDN博客_redis的zset实现原理 0.zset数据结构 [有序集合] [本质上是集合,所有元素不能重复] [分数可以重复(相同 ...

  9. Redis 概念以及底层数据结构

    Redis 简介 REmote DIctionary Server(Redis) 是一个由SalvatoreSanfilippo写的key-value存储系统. Redis是一个开源的使用ANSI C ...

最新文章

  1. 基于SpringBoot + Vue的小程序商城项目(附源码),支持分销、团购、秒杀、优惠券。。。...
  2. 产品诞生过程--导图
  3. P4258-[WC2016]挑战NPC【带花树】
  4. mysql记录当前表数据的数据条数据类型_mysql的表的操作 数据类型
  5. 【待完成】并发包下常用到线程工具类汇总
  6. 计算机体系结构_计算机体系结构知识笔记
  7. 【JAVA】虚拟机指令集
  8. C# this关键字(给底层类库扩展成员方法)
  9. 实验题目用正交多项式做小二乘曲线拟合
  10. 梯度下降(一)--机器学习
  11. adc0808温度换算公式_课程设计-ADC0808设计的调温报警器
  12. NIOS_Altera EPCS下载 注意事项20210815
  13. 在利用DXP2004软件进行PCB设计时——自制元器件封装如何添加网络(布线问题)
  14. 陀螺仪-加速计-磁力计
  15. win7取消计算机密码怎么设置,Win7取消开机密码的方法
  16. AAC 音频数据结构实例分析:
  17. matlab绘制香农定理曲线,基于matla对香农公式仿真.doc
  18. 奇迹暖暖登录显示服务器满,奇迹暖暖登录不是全屏
  19. 被历史遗忘的第一骑兵名将 —— 陈庆之
  20. 华为校园招聘技术类笔试面试经验(摘)

热门文章

  1. 学python有必要用固态硬盘吗-pythonssd
  2. JDBC连接数据库步骤(入门到进阶全)
  3. PVLAN (Private VLAN)
  4. 移动管家汽车手机蓝牙无钥匙解锁方案
  5. SQL数据库常用约束及建表、插入数据时注意事项
  6. 关于_map文件的全面解析
  7. 【个人笔记】SIPp学习-注册,呼叫与超时
  8. 区块链热点!STO被政府严令禁止
  9. linux 解压所有以zip结尾的文件_Linux下的压缩zip,解压缩unzip命令详解及实例
  10. 触摸屏 服务器系统,IP网络触摸屏服务器 SK1606