快速列表

  • 一. 基本结构
    • ①. 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. lamp wordpress
  2. Silverlight实用窍门系列:51.Silverlight页面控件的放大缩小、Silverlight和Html控件的互相操作...
  3. h5页面如何预览excel文件_如何让excel文件读取变得更简单
  4. CDialog中使用工具栏和状态栏
  5. X战警大战复联要来了?迪士尼收购21世纪福克斯后开始狂秀IP...
  6. 广西大学计算机英语复试的内容,广西大学计算机专业的研究生复试时
  7. 加速VS2005 or VS2008
  8. 图解: 线程状态转换(线程生命周期这一篇够用了)
  9. Windows无法调节显示亮度
  10. 国培计算机网络技术培训心得,2017国培学习心得体会及感受
  11. 浅谈对工厂方法模式的理解
  12. Teardrop代码编程,创建虚假包
  13. __virtual__ returned False: cannot import name certs ---saltstack异常解决
  14. Windows和ubuntu下一些提升效率的工具知识点以及typora和Obsidian配置
  15. 仓储货架安全在线监测系统TMP-ANG-S002
  16. 动力电池系统介绍(四)——电磁兼容介绍
  17. 转载:群联PS2251-07主控(Kingston64G)量产CD-ROM+移动磁盘模式过程记录
  18. 专网应急通信系统|北峰MESH无线自组网系统
  19. CD4017 十进制计数器工作原理及应用大全(不断更新中......)
  20. Dynamics NAV4.0升级到Dynamics 365 Business Central180遇到的一些问题(持续更新中....)

热门文章

  1. 哈希消息认证码HmacSHA256-javascript版
  2. 如何区分光接入网OLT, ONU, ODN,ONT?
  3. 关于maxIdle ,MaxActive,maxWait介绍
  4. 忆享聚焦|全球云计算市场份额、数字虚拟人、“元宇宙”实体店……近期行业热点速览
  5. Linux可重入函数
  6. Unity 实现人工智能语音
  7. 系统克隆 机械硬盘无缝迁移到ssd
  8. ThreeJS加载geojson数据实现3D地图
  9. P1258 小车问题(二分法)
  10. 低频数字相位测量仪的介绍