一、前言

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的更多相关文章

  1. redis五种数据类型的使用(zz)

    redis五种数据类型的使用 redis五种数据类型的使用 (摘自:http://tech.it168.com/a2011/0818/1234/000001234478_all.shtml ) 1.S ...

  2. redis五种数据类型的使用

    redis五种数据类型的使用 redis五种数据类型的使用 (摘自:http://tech.it168.com/a2011/0818/1234/000001234478_all.shtml ) 1.S ...

  3. redis五种数据类型的使用场景

    string 1.String 常用命令: 除了get.set.incr.decr mget等操作外,Redis还提供了下面一些操作: 获取字符串长度 往字符串append内容 设置和获取字符串的某一 ...

  4. Redis五种数据类型-设置key的过期时间

    1.redis命令客户端 [root@localhost bin]# ./redis-cli 127.0.0.1:6379> #是否运行着 127.0.0.1:6379> ping PON ...

  5. redis 五种数据类型

    前言 前面学会了单机, 学会了集群, 但是redis咋用啊? 或者说, redis支持哪些数据类型呢? 常用的有五种: String , Hash, List, Set, zset(SortedSet ...

  6. (转) 淘淘商城系列——Redis五种数据类型介绍

    http://blog.csdn.net/yerenyuan_pku/article/details/72855562 Redis支持五种数据类型:string(字符串),hash(哈希),list( ...

  7. 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的五种数据类 ...

  8. redis五种数据类型的应用

    redis的五种数据类型和使用场景 string类型 string类型多用于缓存 set key value(value可以为json字符串) setnx多用于分布式锁(后面详细整理) 计数器 inc ...

  9. 《闲扯Redis三》Redis五种数据类型之List型

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

随机推荐

  1. 打造Worktile敏捷开发管理工具的思与惑

    从2019年初,我们团队准备开发一款适合研发团队使用的敏捷开发管理工具,那时候我们也在思考,到底什么样的工具才算是优秀的研发管理工具,研发管理的场景.方法和流派有很多,市面上关于研发管理工具的产品也是 ...

  2. Input标签中属性的注意点

    readonly 只读字段,即用户不可更改,但可以通过tab切换到该字段,还可以选中复制该字段 step 输入合法的数字间隔,当step属性的值为负数或0时默认为1,可以配合max,min属性来创建合 ...

  3. IC设计流程概述

    芯片设计分为前端设计和后端设计,前端设计(也称逻辑设计)和后端设计(也称物理设计)并没有统一严格的界限,涉及到与工艺有关的设计就是后端设计. Front-end design flow 1. 规格制定 ...

  4. windows使用的奇淫技巧

    找回刚才打开的网页 记事本 特殊符号输入 窗口变化为1/2,1/4 批量重命名 复制文件路径 万能命令

  5. 还不懂 ConcurrentHashMap ?这份源码分析了解一下

    上一篇文章介绍了 HashMap 源码,反响不错,也有很多同学发表了自己的观点,这次又来了,这次是 ConcurrentHashMap 了,作为线程安全的HashMap ,它的使用频率也是很高.那么它 ...

  6. D. Fight with Monsters

    D. Fight with Monsters time limit per test 1 second memory limit per test 256 megabytes input standa ...

  7. 3.26java作业

    1.编写程序, 输入变量x的值,如果是1,输出x=1,如果是5,输出x=5,如果是 10,输出 x=10,除了以上几个值,都输出x=none.(知识点:if条件语句) package fda; imp ...

  8. Docket 容器引擎

    Docker 是世界领先的软件容器平台.是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中, 然后发布到任何流行的Linux或Windows机器上,可以实现虚拟化(软件 ...

  9. hadoop+zookeeper集群高可用搭建

                                                                  hadoop+zookeeper集群高可用搭建 Senerity 发布于 2 ...

  10. MySQL 数据备份与同步

    前段时间使用MySQL作为数据存储做了一个小项目.项目上线运行了几十天之后,数据已经越来越多,达到了100多M.用mysqldump每天备份全量数据然后传输到另外一台机器上这种方式进行数据备份,久而久 ...