Redis的数据结构之List

190 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第25天,点击查看活动详情

前言

数据结构中数组和链表通常都是最常见的数据结构,那么Redis的list的底层数据结构是采用何种数据结构实现的呢?

数据结构存储

不同的的Redis版本list的数据结构有所不同,Redis3.2之前的版本,List的数据结构分为双向链表、ziplist,而在Redis3.2之后的版本出现了quickList数据结构存储。

linkedlist

与java的中的linkedlist类似,Redis中的linkList是一个双向链表,具体结构如下:

图片.png

说明:

  • pre:指向前一个节点
  • next:指针指向后一个节点
  • value保存着当前节点对应的数据对象
  • head:指向链表的头节点
  • tail:指向链表的尾节点
  • len:表示这个链表共有多少个节点,这样就可以在O(1)的时间复杂度内获得链表的长度.

ziplist

zipList称之为压缩列表,是一种非常节省内存的结构,其数据结构如下:

图片.png

说明:

  • zlbytes:列表长度
  • zltail : 列表尾的偏移量
  • zllen:表示entry的个数
  • zlend: 列表结束

其中Entry的结构如下:

图片.png

  • prelen:保存的是前一个entry节点的长度,这样在倒序遍历时就可以通过这个参数定位到上一个entry的位置
  • encoding:保存了content的编码类型
  • content:则是保存的元素内容,它是optional类型的,表示这个字段是可选的。当content是很小的整数时,它会内联到content字段的尾部.

quickList

qucikList是由zipList和双向链表linkedList组成的混合体。它将linkedList按段切分,每⼀段使⽤zipList来紧凑存储,多个zipList之间使⽤双向指针串接起来,其结构示意图如下:

图片.png

小结

关于这三种数据结构存储的优缺点分别如下:

图片.png

常用命令

图片.png

lpush 从头部添加元素

图片.png

lpush 从尾部添加元素

图片.png

lrange 获取某个区间的值

图片.png

lpop 从左边删除元素

图片.png

lpop 从右边删除元素

图片.png

llen list的长度

图片.png

lindex 通过下标获取值

图片.png

lrem 删除指定元素

图片.png

ltirm 截断列表

图片.png

应用场景

  • 由于list存在lpush/rpop命令,我们可以采用list作为简单的消息队列.

特别说明:采用rpop命令时,即使没有新的消息写入list,消费者也要不停地调用rpop命令,这就会导致消费者程序的 CPU 一直消耗在执行 RPOP 命令上,带来不必要的性能损失,可以采用BRPOP命令也称为阻塞式读取,客户端在没有读到队列数据时,自动阻塞,直到有新的数据写入队列,再开始读取新数据。和消费者程序自己不停地调用 RPOP 命令相比,这种方式能节省 CPU 开销。

总结

本文讲解了Redis的list的数据结构存储和相关的基础命令,如有疑问可以随时反馈。