《闲扯Redis五》List数据类型底层之quicklist
一、前言
Redis 提供了5种数据类型:String(字符串)、Hash(哈希)、List(列表)、Set(集合)、Zset(有序集合),理解每种数据类型的特点对于redis的开发和运维非常重要。

Redis 中的 list 是我们经常使用到的一种数据类型,根据使用方式的不同,可以应用到很多场景中。
二、底层解析
1、上节回顾
上节《闲扯Redis四》List数据类型底层编码转换 说道,在 3.0 版本的 Redis 中,List 类型有两种实现方式:
1、使用压缩列表(ziplist)实现的列表对象。
2、使用双端链表(linkedlist)实现的列表对象。
在 3.2 版本后新增了 quicklist 数据结构实现了 list,现在就来分析下 quicklist 的结构
2、官方描述
先来看看 Redis 官方对 quicklist 的描述:
A doubly linked list of ziplists
A generic doubly linked quicklist implementation
可见 quicklist 是一个双向链表,并且是一个 ziplist 的双向链表,也就是说 quicklist 的每个节点都是一个 ziplist。而通过前面的文章咱们可以知道,ziplist 本身也是一个能维持数据项先后顺序的列表,而且数据项保存在一个连续的内存块中。那是不是意味着 quicklist 结合了压缩列表和双端链表的特点呢!
3、结构分析
quicklist 结构定义
/*
* quicklist
*/
typedef struct quicklist {
//头结点
quicklistNode *head;
//尾节点
quicklistNode *tail;
//所有ziplist中entry数量
unsigned long count;
//quicklistNodes节点数量
unsigned int len;
//ziplist中entry能保存的数量,由list-max-ziplist-size配置项控制
int fill : 16;
//压缩深度,由list-compress-depth配置项控制
unsigned int compress : 16;
} quicklist;
quicklist 结构属性注释
注释:
fill :ziplist 中 entry 能保存的数量,由 list-max-ziplist-size 配置项控制
表示了单个节点(quicklistNode)的负载比例(fill factor),负数限制 quicklistNode 中的 ziplist 的字节长度,
正数限制 quicklistNode 中的 ziplist 的最大长度。
-5: 最大存储空间: 64 Kb <-- 通常情况下不要设置这个值
-4: 最大存储空间: 32 Kb <-- 非常不推荐
-3: 最大存储空间: 16 Kb <-- 不推荐
-2: 最大存储空间: 8 Kb <-- 推荐
-1: 最大存储空间: 4 Kb <-- 推荐
对于正整数则表示最多能存储到你设置的那个值, 当前的节点就装满了
通常在 -2 (8 Kb size) 或 -1 (4 Kb size) 时, 性能表现最好
compress :压缩深度,由 list-compress-depth 配置项控制
表示 quicklist 中的节点 quicklistNode, 除开最两端的 compress 个节点之后, 中间的节点都会被压缩(LZF压缩算法)。
quicklistNode 结构定义
typedef struct quicklistNode {
//前节点指针
struct quicklistNode *prev;
//后节点指针
struct quicklistNode *next;
//数据指针。当前节点的数据没有压缩,那么它指向一个ziplist结构;否则,它指向一个quicklistLZF结构。
unsigned char *zl;
//zl指向的ziplist实际占用内存大小。需要注意的是:如果ziplist被压缩了,那么这个sz的值仍然是压缩前的ziplist大小
unsigned int sz;
//ziplist里面包含的数据项个数
unsigned int count : 16;
//ziplist是否压缩。取值:1--ziplist,2--quicklistLZF
unsigned int encoding : 2;
//存储类型,目前使用固定值2 表示使用ziplist存储
unsigned int container : 2;
//当我们使用类似lindex这样的命令查看了某一项本来压缩的数据时,需要把数据暂时解压,这时就设置recompress=1做一个标记,等有机会再把数据重新压缩
unsigned int recompress : 1;
unsigned int attempted_compress : 1; /* node can't compress; too small */
unsigned int extra : 10; /* more bits to steal for future usage */
} quicklistNode;
quicklistLZF 结构定义
typedef struct quicklistLZF {
unsigned int sz; //压缩后的ziplist大小
char compressed[];//柔性数组,存放压缩后的ziplist字节数组
} quicklistLZF;
4、quicklist 结构图
根据上述结构体定义,咱们可以绘制一下 quicklist 的结构:
三、要点总结
1、双端链表
1.双端链表便于在表的两端进行 push 和 pop 操作,但是它的内存开销比较大;
2.双端链表每个节点上除了要保存数据之外,还要额外保存两个指针;
3.双端链表的各个节点是单独的内存块,地址不连续,节点多了容易产生内存碎片;
2、压缩列表
1.ziplist 由于是一整块连续内存,所以存储效率很高;
2.ziplist 不利于修改操作,每次数据变动都会引发一次内存的 realloc;
3.当 ziplist 长度很长的时候,一次 realloc 可能会导致大批量的数据拷贝,进一步降低性能;
3、quicklist
1.空间效率和时间效率的折中;
2.结合了双端链表和压缩列表的优点;
《闲扯Redis五》List数据类型底层之quicklist的更多相关文章
- redis五种数据类型的使用(zz)
redis五种数据类型的使用 redis五种数据类型的使用 (摘自:http://tech.it168.com/a2011/0818/1234/000001234478_all.shtml ) 1.S ...
- redis五种数据类型的使用
redis五种数据类型的使用 redis五种数据类型的使用 (摘自:http://tech.it168.com/a2011/0818/1234/000001234478_all.shtml ) 1.S ...
- redis五种数据类型的使用场景
string 1.String 常用命令: 除了get.set.incr.decr mget等操作外,Redis还提供了下面一些操作: 获取字符串长度 往字符串append内容 设置和获取字符串的某一 ...
- Redis五种数据类型-设置key的过期时间
1.redis命令客户端 [root@localhost bin]# ./redis-cli 127.0.0.1:6379> #是否运行着 127.0.0.1:6379> ping PON ...
- redis 五种数据类型
前言 前面学会了单机, 学会了集群, 但是redis咋用啊? 或者说, redis支持哪些数据类型呢? 常用的有五种: String , Hash, List, Set, zset(SortedSet ...
- (转) 淘淘商城系列——Redis五种数据类型介绍
http://blog.csdn.net/yerenyuan_pku/article/details/72855562 Redis支持五种数据类型:string(字符串),hash(哈希),list( ...
- Redis五种数据类型应用场景
目录 1.1 回顾 2.1 应用场景 2.1.1 String 2.1.2 Hash 2.1.3 List 2.1.4 Zet 2.1.5 zset 3.1 小结 1.1 回顾 Redis的五种数据类 ...
- redis五种数据类型的应用
redis的五种数据类型和使用场景 string类型 string类型多用于缓存 set key value(value可以为json字符串) setnx多用于分布式锁(后面详细整理) 计数器 inc ...
- 《闲扯Redis三》Redis五种数据类型之List型
一.前言 Redis 提供了5种数据类型:String(字符串).Hash(哈希).List(列表).Set(集合).Zset(有序集合),理解每种数据类型的特点对于redis的开发和运维非常重要. ...
随机推荐
- 装numpy 环境:python3.4+ windows7 +64位系统
机器学习实战python 因为图像处理的原因,初步学习机器学习,选用语言python,参考书籍<机器学习实战> 环境:python3.4+ windows7 +64位系统 首先,今天解决的 ...
- NOI ONLINE 入门组 魔法 矩阵快速幂
做了这道题我才发现NOI入门组!=NOIP普及组 题目链接 https://www.luogu.com.cn/problem/P6190 题意 给出一张有向图,你有K次机会可以反转一条边的边权,即让它 ...
- Transformers 中使用 TorchScript | 四
作者|huggingface 编译|VK 来源|Github 注意:这是我们使用TorchScript进行实验的开始,我们仍在探索可变输入大小模型的功能.它是我们关注的焦点,我们将在即将发布的版本中加 ...
- C的变量类型、作用域与生命周期的总结
C的变量类型.作用域与生命周期的总结 最近在看"C Programing Language" (Kernighan, Ritchie)关于外部变量的讨论,之前在学C的时候对这些ex ...
- JVM基础结构与字节码执行引擎
JVM基础结构 JVM内部结构如下:栈.堆. 栈 JVM中的栈主要是指线程里面的栈,里面有方法栈.native方法栈.PC寄存器等等:每个方法栈是由栈帧组成的:每个栈帧是由局部变量表.操作数栈等组成. ...
- python:<class 'numpy.ndarray'>的学习
在学习opencv-python的时候,给出图片地址再调用cv2.imread("地址"),发现出创建的是numpy类型的ndarray对象,用来存放多维数组的对象 # 导入cv2 ...
- PTA数据结构与算法题目集(中文) 7-9
PTA数据结构与算法题目集(中文) 7-9 7-9 旅游规划 (25 分) 有了一张自驾旅游路线图,你会知道城市间的高速公路长度.以及该公路要收取的过路费.现在需要你写一个程序,帮助前来咨询的游 ...
- java中OOM错误解析(面试可以聊的东西)
嗯,生活加油鸭.... 实习中遇到OOM错误 GC overhead limit exceeded 问题,所以整理一下OOM异常问题: 先看一下“阿里的开发手册”对OOM的描述: OOM,全称“Out ...
- redis持久化文件问题
问题: Can't open the append-only file Permission denied 发现缺少文件:/data/缺少appendonly.aof,dump.rdb文件. 手动创建 ...
- 多数据源系统接入mybatis-plus, 实现动态数据源、动态事务。
目录: 实现思想 导入依赖.配置说明 代码实现 问题总结 一.实现思想 接手一个旧系统,SpringBoot 使用的是纯粹的 mybatis ,既没有使用规范的代码生成器,也没有使用 JPA 或者 m ...
