深入学习Redis(四),基本类型【List】剖析

更多精彩文章,关注公众号【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资源免费等你来拿!!!``

                         

阅读 157发布于 10月22日
推荐阅读
目录