redis list 取出所有数据 redis list 取值_双向链表


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

存储类型

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


redis list 取出所有数据 redis list 取值_list取值_02


操作命令

元素增减


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


redis list 取出所有数据 redis list 取值_redis list 取出所有数据_03


java架构师:作为Java开发,我是如何在一年之内,让自己的月薪爆炸式提升!!zhuanlan.zhihu.com


redis list 取出所有数据 redis list 取值_list取值_04


存储( 实现) 原理

在早期的版本中,数据量较小时用 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;


redis list 取出所有数据 redis list 取值_List_05

源码结构图

ziplist 的结构前面已经说过了,不再重复,请移步。

应用场景

用户消息时间线 timeline

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


redis list 取出所有数据 redis list 取值_双向链表_06


消息队列

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

BLPOPBLPOP key1 timeout

会阻塞列表直到等待超时或发现可弹出元素为止。

BRPOP:BRPOP key1 timeout

素会阻塞列表直到等待超时或发现可弹出元素为止。

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

栈:先进后出:rpush brpop