Redis底层数据结构之List

文章目录

    • [1. Redis 6的list源码分析](#1. Redis 6的list源码分析)
    • [1. Redis 7的list源码分析](#1. Redis 7的list源码分析)

1. Redis 6的list源码分析

首先我们查看一下redis 6关于list的相关配置:

sql 复制代码
config get list*

可以看见redis 6的quicklist底层使用的数据结构是ziplist

list-compress-depth:表示一个quicklist两端不被压缩的节点数量,这里的节点指的是quicklist双向链表的节点,而不是指ziplist里面的数据项个数

list-compress-depth的取值含义如下:

  • 0:是个特殊值,表示都不压缩,这是redis的默认值
  • 1:表示quicklist两端各有一个节点不压缩
  • 2:表示quicklist两端各有两个节点不压缩

...以此类推

list-max-ziplist-size -2:当取正值时候,表示按照数据项个数来限定每个quicklist节点上的ziplist的长度。比如将这个参数配置成5,表示每个quicklist节点的ziplist最多包含5个数据项,当取负值的时候,表示按照占用的节点数来限制每个quicklist节点上的ziplist长度,它只能取-1到-5这5个值,每个值的含义如下:

  • -5:每个quicklist节点上的ziplist大小不能超过64kb
  • -4:每个quicklist节点上的ziplist大小不能超过32kb
  • -3:每个quicklist节点上的ziplist大小不能超过16kb
  • -2:每个quicklist节点上的ziplist大小不能超过8kb(默认值)
  • -1:每个quicklist节点上的ziplist大小不能超过4kb

所以在redis 6时list用quicklist来存储,quicklist存储了一个双向链表,链表的每一个节点都是ziplist

  • 总结:

在较早的rendis(redis3之前)中,list有两种底层实现:

  1. 当列表中的元素的长度比较小或者数量比较少的时候,采用压缩列表ziplist来存储
  2. 当列表对象中的元素的长度比较大或者数量比较多的时候,则会转而使用双向列表linklist来存储

但是这两者数据结构各有优缺点:

  1. ziplist的有点是内存紧凑,访问效率高,缺点是更新效率低(可能出现连锁更新现象),并且数据量较多时,可能导致大量的内存复制
  2. linkedlist的优点就是修改的效率高,但是需要额外的内存,并且节点较多时,会产生大量的内存碎片

所以为了结合两者的优点,在redis 3.2之后,list底层的实现变成了快速列表:quicklist

quicklist本质上来说就是ziplist+linkedlist

下面来分析源码证明上面的数据结构,首先打开quicklist.h:

c 复制代码
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;

上面时quicklist的结构,首先是head和tail,分别指向第一个quicklistNode和最后一个 quicklistNode,具体的结构如下:

下面我们看看quicklistNode的结构:

c 复制代码
typedef struct quicklistNode {
    struct quicklistNode *prev;
    struct quicklistNode *next;
    //指向一个ziplist
    unsigned char *zl;
    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;

总的来说,zquicklist就是下面一个结构:

1. Redis 7的list源码分析

redis 7的quicklist和redis 6的quicklist的区别就是,redis 7将redis 6中的ziplist换成了listpack数据结构,其它都大同小异。

sql 复制代码
config get list*
相关推荐
hweiyu007 小时前
Redis命令:HTTL
redis·缓存
h_a_o777oah7 小时前
【树论】树链剖分:将树形结构转化为线性结构以处理树上路径问题(洛谷 P3384 附C++代码模板)
数据结构·算法·线段树·acm·树链剖分·树论·重链剖分
HEJOO97 小时前
指针的算术运算详解
java·数据结构·算法
Coder-magician7 小时前
《代码随想录》刷题打卡day47:并查集-part01
数据结构·算法·图论
垆边人似月.7 小时前
VLAN 资源池(100~200 分档)
数据结构·算法
程序员清风9 小时前
算法与数据结构入门:复杂度、数组与链表
数据结构·算法·链表
樱花落木兰12 小时前
分布式登录实战:Session 会话共享改造,Redis 存储用户登录状态
java·javascript·数据库·redis·分布式·缓存
Logic10112 小时前
C语言/数据结构排序题解:三个数的最大乘积——排序后比较两种候选情况
c语言·数据结构·数组·排序·时间复杂度·算法题·负数处理
ShineWinsu12 小时前
对于Redis:Steam、Geospatial、Hyperloglog、Bitmap、Bitfield类型的解析
数据库·c++·redis·分布式·缓存·面试·zset
殷色玫瑰13 小时前
C++ string类详解:常用接口、字符串操作与模拟实现
java·linux·c语言·开发语言·数据结构·c++