深入学习Redis四基本类型List剖析

41次阅读

共计 1998 个字符,预计需要花费 5 分钟才能阅读完成。

更多精彩文章,关注公众号【ToBeTopJavaer】,更有数万元精品 vip 资源免费等你来拿!!!

接下来我们要剖析的基本类型是 List,相信大家对 List 都不会陌生吧,下面我们将深入源码剖析 Redis 中 List 的实现。

存储类型

存储有序的字符串(从左到右),元素可以重复。可以充当队列和栈的角色。

操作命令

元素增减

lpush queue a
lpush queue b c
rpush queue d e
lpop queue
rpop queue
​blpop queue
brpop queue

取值

lindex queue 0
lrange queue 0 -1

存储(实现)原理

在早期的版本中,数据量较小时用 ziplist 存储,达到临界值时转换为 linkedlist 进行存储,分别对应 OBJ_ENCODING_ZIPLIST 和 OBJ_ENCODING_LINKEDLIST。

3.2 版本之后,统一用 quicklist 来存储。quicklist 存储了一个双向链表,每个节点都是一个 ziplist。

127.0.0.1:6379> object encoding queue
"quicklist"

什么是 quicklist?

quicklist(快速列表)是 ziplist 和 linkedlist 的结合体。

quicklist.h 源码如下,head 和 tail 指向双向列表的表头和表尾

typedef struct quicklist {
  quicklistNode \*head; /\* 指向双向列表的表头 \*/
  quicklistNode \*tail; /\* 指向双向列表的表尾 \*/
  unsigned long count; /\* 所有的 ziplist 中一共存了多少个元素 \*/
  unsigned long len; /\* 双向链表的长度,node 的数量 \*/
  int fill : 16; /\* fill factor for individual nodes \*/
  unsigned int compress : 16; /\* 压缩深度,0:不压缩;\*/
} quicklist;

redis.conf 相关参数:

list-max-ziplist-size(fill)

正数表示单个 ziplist 最多所包含的 entry 个数。

负数代表单个 ziplist 的大小,默认 8k。

-1:4KB;-2:8KB;-3:16KB;-4:32KB;-5:64KB

list-compress-depth(compress)

压缩深度,默认是 0。

其它值含义:1:首尾的 ziplist 不压缩;2:首尾第一第二个 ziplist 不压缩,以此类推

quicklistNode 中的 *zl 指向一个 ziplist,一个 ziplist 可以存放多个元素。

源码如下:

typedef struct quicklistNode {
  struct quicklistNode \*prev; /\* 前一个节点 \*/
  struct quicklistNode \*next; /\* 后一个节点 \*/
  unsigned char \*zl; /\* 指向实际的 ziplist \*/
  unsigned int sz; /\* 当前 ziplist 占用多少字节 \*/
  unsigned int count : 16; /\* 当前 ziplist 中存储了多少个元素,占 16bit(下同),最大 65536 个 \*/
  unsigned int encoding : 2; /\* 是否采用了 LZF 压缩算法压缩节点,1:RAW 2:LZF \*/
  unsigned int container : 2; /\* 2:ziplist,未来可能支持其他结构存储 \*/
  unsigned int recompress : 1; /\* 当前 ziplist 是不是已经被解压出来作临时使用 \*/
  unsigned int attempted\_compress : 1; /\* 测试用 \*/
  unsigned int extra : 10; /\* 预留给未来使用 \*/
} quicklistNode;

源码结构图

ziplist 的结构在探讨 Hash 时已经说过了,不再重复。

应用场景

用户消息时间线 timeline

因为 List 是有序的,可以用来做用户时间线

消息队列

List 提供了两个阻塞的弹出操作:BLPOP/BRPOP,可以设置超时时间。

BLPOP:BLPOP key1 timeout 移出并获取列表的第一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。

BRPOP:BRPOP key1 timeout 移出并获取列表的最后一个元素,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。

队列:先进先出:rpush blpop,左头右尾,右边进入队列,左边出队列。

栈:先进后出:rpush brpop

今天我们从底层源码剖析了基本数据类型 List,接下来我们将会对剩下的几个常用的基本类型的深入探讨,敬请期待。

更多精彩文章,关注公众号【ToBeTopJavaer】,更有数万元精品 vip 资源免费等你来拿!!!

                         

正文完
 0