Redis的底层数据结构----快速列表_quicklist
快速列表
- 一. 基本结构
- ①. 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相关推荐
- Redis专题-底层数据结构与使用场景
Redis介绍 Redis是一种基于键值对的NoSQL数据库,是一个基于内存中的数据结构存储系统,可以用作数据库.缓存和消息中间件.它支持以string(字符串),hash(哈希),list(列表), ...
- redis:redis的底层数据结构
高效的数据结构 redis中的数据结构有2种意思: (redis本质上是一个hashmap) redis键值对中的值的数据类型,也就是数据的保存形式,常用的有5种:String(字符串).List(列 ...
- redis 底层数据结构 压缩列表 ziplist
压缩列表是列表键和哈希键的底层实现之一.当一个列表键只包含少量列表项,并且每个列表项要么就是小整数,要么就是长度比较短的字符串,redis就会使用压缩列表来做列表键的底层实现 当一个哈希键只包含少量键 ...
- 四、redis的底层数据结构
1.演示数据类型的实现 上篇博客我们在介绍 key 相关命令的时候,介绍了如下命令: OBJECT ENCODING key 该命令是用来显示那五大数据类型的底层数据结构. 比如对于 string 数 ...
- c++ map底层_Redis详解(四)------ redis的底层数据结构
> 本系列教程持续更新,可以微信搜索「 IT可乐 」第一时间阅读.回复<电子书>有我为大家特别筛选的书籍资料 上一篇博客我们介绍了 redis的五大数据类型详细用法,但是在 Redi ...
- Redis六种底层数据结构
文章目录 一.简单动态字符串 1.SDS的结构定义 2.SDS和c字符串的区别 1)SDS获取字符串长度复杂度为常数 2)SDS杜绝了缓冲区溢出 3)减少内存重分配次数 4)二进制安全 5)SDS兼容 ...
- 图解 Redis String 底层数据结构 SDS 与计数器实战
我是 Redis,给开发者提供了 String(字符串).Hashes(散列表).Lists(列表).Sets(无序集合).Sorted Sets(可根据范围查询的排序集合).Bitmap(位图).H ...
- Redis zset 底层数据结构之跳表
参考: redis zset 内部的实现原理_行走在江湖的博客-CSDN博客_redis的zset实现原理 0.zset数据结构 [有序集合] [本质上是集合,所有元素不能重复] [分数可以重复(相同 ...
- Redis 概念以及底层数据结构
Redis 简介 REmote DIctionary Server(Redis) 是一个由SalvatoreSanfilippo写的key-value存储系统. Redis是一个开源的使用ANSI C ...
最新文章
- lamp wordpress
- Silverlight实用窍门系列:51.Silverlight页面控件的放大缩小、Silverlight和Html控件的互相操作...
- h5页面如何预览excel文件_如何让excel文件读取变得更简单
- CDialog中使用工具栏和状态栏
- X战警大战复联要来了?迪士尼收购21世纪福克斯后开始狂秀IP...
- 广西大学计算机英语复试的内容,广西大学计算机专业的研究生复试时
- 加速VS2005 or VS2008
- 图解: 线程状态转换(线程生命周期这一篇够用了)
- Windows无法调节显示亮度
- 国培计算机网络技术培训心得,2017国培学习心得体会及感受
- 浅谈对工厂方法模式的理解
- Teardrop代码编程,创建虚假包
- __virtual__ returned False: cannot import name certs ---saltstack异常解决
- Windows和ubuntu下一些提升效率的工具知识点以及typora和Obsidian配置
- 仓储货架安全在线监测系统TMP-ANG-S002
- 动力电池系统介绍(四)——电磁兼容介绍
- 转载:群联PS2251-07主控(Kingston64G)量产CD-ROM+移动磁盘模式过程记录
- 专网应急通信系统|北峰MESH无线自组网系统
- CD4017 十进制计数器工作原理及应用大全(不断更新中......)
- Dynamics NAV4.0升级到Dynamics 365 Business Central180遇到的一些问题(持续更新中....)