首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Redis 数据类型:List 列表的深度解析与应用

Redis 数据类型:List 列表的深度解析与应用

作者头像
Undoom
发布2025-08-23 08:14:04
发布2025-08-23 08:14:04
3300
举报
文章被收录于专栏:学习学习

前言

Redis 中的 List 类型是一种灵活的数据结构,其功能类似于编程语言中的数组或顺序表,但其内部实现更接近于双端队列 (deque)。这使得在列表的头部和尾部进行元素的插入和删除操作都非常高效。

List 类型的主要特性包括:

  • 有序性:列表中的元素是按照插入顺序排列的。
  • 可重复性:与 Set 不同,List 允许存储重复的元素。
  • 高效的头尾操作:通过 lpush、rpush、lpop 和 rpop 等命令,可以快速地在列表两端添加或移除元素,因此常被用作栈或队列。

Redis 的 List 类型是实现消息队列等模式的基石,在 Redis 早期版本中,它是构建消息队列的主要方式,后来 Redis 也引入了更为专业的 Stream 类型。

列表list相当于数组或者顺序表

image.png
image.png

redis的下标支持负数下标,getrange

右侧插入叫做rpush,右侧删除叫做rpop 左侧插入叫做lpush,左侧删除叫做lpop

list内部的结构(编码方式),并非是一个简单的数组,而是更接近于“双端队列(deque)”

  • 列表中的元素是有序的
  • 列表中区分获取和删除的区别 lindex能获取元素的值 lrem也能返回被删除的元素的值
  • 列表中的元素是允许重复的 想hash这样的类型,field是不能重复的

当前list,头和尾都能高效的插入删除元素,就可以把这个list当成一个栈、队列来使用

redis有一个典型的应用场景,就是作为消息队列,最早的时候,就是通过list类型,后来redis又提供了一个stream类型

lpush、lrange

代码语言:javascript
复制
lpush key element [element ...]

lpush一次可以插入一个元素,也可以插入多个元素 按照顺序进行头插元素 1、2、3、4 插入完成之后,4是最前面的

时间复杂度是O(1)

返回的是list的长度

如果key已经存在,并且key对应的value类型不是list的话,此时lpush就会报错 redis中所有的数据类型的操作都是这样的,必须保证类型匹配

image.png
image.png

第一次返回长度为4,第二次为8

插入完成之后使用lrange查看我们list的内容

代码语言:javascript
复制
lrange key start stop

后面我们需要指定一段区间的,也是闭区间的,下标也是支持负数的

使用命令就能查看整个list的内容了

代码语言:javascript
复制
lrange key  0 -1
image.png
image.png

如果给到的下标超出了范围会出现什么情况呢?

redis的做法,是直接尽可能的获取到给定区间的元素,如果给定区间非法,比如超出下标,尽可能获取到内容

image.png
image.png
image.png
image.png

lpushx、rpush、rpushx

lpushx:如果key存在时,将一个或者多个元素从左侧放入(头插)到list中。不存在,直接返回

代码语言:javascript
复制
lpushx key element [element...]

时间复杂度是O(1) 返回值是插入后list的长度

image.png
image.png

rpush将一个或者多个元素从右侧插入到list中

代码语言:javascript
复制
rpush key element [element...]
image.png
image.png

rpushx:如果key存在时,将一个或者多个元素从右侧放入(尾插)到list中。不存在,直接返回

代码语言:javascript
复制
rpushx key element [element...]

lpop、rpop

lpop:返回值是取出的元素或者nil,时间复杂度是O(1)

代码语言:javascript
复制
lpop key
image.png
image.png

rpop:从尾部删除数据,返回的即是删除的元素或者nil

代码语言:javascript
复制
rpop key [count]

可以发现这里是一个count的,说明我们可以指定删除数据的个数的 lpop是不支持后面加上个数的,但是rpop是支持的

image.png
image.png
image.png
image.png

lindex、linsert、llen

index:给定下标,获取到对应的元素 时间复杂度是O(N),N指的是list中元素个数 如果下标非法的话,会返回一个nil空值

代码语言:javascript
复制
lindex key index

下标是从0开始的,并且支持负数下标

image.png
image.png

linsert:在指定位置插入元素 时间复杂度是O(N) N表示列表的长度 返回值:插入后的list长度

代码语言:javascript
复制
linsert key <before|after> pivot element

before|after这两个选项是说明是插入到元素之前还是元素之后,这两个选项二选一即可

pivot就是插入元素的基准,是插入到这个元素的左侧还是右侧

element就是插入的元素

image.png
image.png
image.png
image.png

但是如果这个基准值如果存在多个的话如何 下面这里只插入到了第一个4的前面

image.png
image.png

linsert进行插入的时候,要根据基准值,找到对应的位置,从左往右找,找到第一个符合基准值的位置即可

llen:获取list长度 时间复杂度O(1)

代码语言:javascript
复制
llen key
image.png
image.png

lerm

rem是remove的缩写

代码语言:javascript
复制
lrem key count element

count表示元素的个数 element表示的是删除元素的值 时间复杂度是O(N+M) N是list的长度,M是多少个元素要被删除,就是count的大小

  • 如果count大于0的话,我们在删除这个element的时候是从左往右进行元素的查找的 如果此时的list是1 2 3 4 1 2 3 4 1 2 3 4 的话,我们lrem key 2 1,找到1,删除两次,所以就从左往右查找1,删除两个1即可
image.png
image.png
image.png
image.png
  • 如果count<0的话,我们在删除这个element的时候是从右往左进行元素的查找的 如果此时的list是1 2 3 4 1 2 3 4 1 2 3 4 的话,我们lrem key -2 1,找到1,删除两次,所以就从右往左查找1,删除两个1即可
image.png
image.png
image.png
image.png
  • 如果count=0的话,我们得删除所有对应的元素, 如果此时的list是1 2 3 4 1 2 3 4 1 2 3 4 的话,我们lrem key 0 1,找到1,将list中所有的1删除了
image.png
image.png
image.png
image.png

ltrim 、lset

ltrim这个也是删除list中元素的命令,相较于lrem更加粗暴, 指定一个范围,范围内的保留,范围外的删除 时间复杂度是O(N)

代码语言:javascript
复制
ltrim key start stop

保留start和stop之间区间内的元素(区间外面两边的元素就直接被删除了) 比如说这里将中间的3 4 5 6 都保存了,其他的都删除了

image.png
image.png

lset:根据下标修改元素 时间复杂度O(N)

代码语言:javascript
复制
lset key index element
image.png
image.png

如果下标超过了范围的话,他是会报错提醒的

image.png
image.png

lindex可以很好的处理下标越界的情况,直接返回nil

lset来说则会报错的

blpop、brpop

blpop和brpop是lpop和rpop的阻塞版本,和对应非阻塞版本的作用基本一致

  • 在列表中有元素的情况下,阻塞和⾮阻塞表现是⼀致的。但如果列表中没有元素,⾮阻塞版本会理解返回 nil,但阻塞版本会根据 timeout,阻塞⼀段时间,期间 Redis 可以执⾏其他命令,但要求执⾏该命令的客⼾端会表现为阻塞状态
  • 命令中如果设置了多个键,那么会从左向右进⾏遍历键,⼀旦有⼀个键对应的列表中可以弹出元素,命令⽴即返回。
  • 如果多个客⼾端同时多⼀个键执⾏ pop,则最先执⾏命令的客⼾端会得到弹出的元素。

阻塞:当前的线程不走了,代码不继续执行了 会在满足一定的条件下,被唤醒

这里的两个命令的前缀b就是block的意思

image.png
image.png

redis中的list也相当于阻塞队列一样 线程安全,则只支持“队列为空”的情况,不考虑“队列满”

如果list中存在元素,blpop和brpop就和lpop以及rpop作用相同 如果list为空的话,blpop和brpop就会产生阻塞,直到队列不空为止

使用blpop和brpop的时候,可以显示设置阻塞时间的,阻塞期间redis是可以执行其他的命令的

blpop和brpop并不会对redis服务器产生影响,只是看起来耗时

blpop和brpop都是可以去尝试获取多个key的列表的元素的 多个Key对应多个list的,哪个有元素了,就会返回哪个元素

如果多个客户端同时多一个键执行pop,则最先执行命令的客户端会得到弹出的元素

image.png
image.png
image.png
image.png
image.png
image.png

blpop key [key…]timeout 可以指定一个key或者是多个key 每个key都对应任何一个非空,blpop都能把这里的元素给获取到,立即返回

如果这些list为空的话,此时就需要阻塞等待了,等待其他客户端往这些list中插入元素了

次数还能指定超时时间,单位是秒

1)针对一个非空list进行操作

image.png
image.png
image.png
image.png

返回的结果相当于是一个pair

一方面告诉我们当前的数据来自于哪个key,另一个方面会告诉我们取到的数据是啥

2)针对一个空链表进行操作

image.png
image.png

3)针对多个Key进行操作

image.png
image.png

brpop效果和blpop完全于一样

这两个阻塞命令主要用途就是来作为消息队列

命令总结

好的,这是根据您提供的图片生成的表格:

操作类型

命令

时间复杂度

添加

rpush key value [value ...]

O(k), k 是元素个数

lpush key value [value ...]

O(k), k 是元素个数

`linsert key before

after pivot value`

O(n), n 是 pivot 距离头尾的距离

查找

lrange key start end

O(s+n), s 是 start 偏移量, n 是 start 到 end 的范围

lindex key index

O(n), n 是索引的偏移量

llen key

O(1)

删除

lpop key

O(1)

rpop key

O(1)

lrem key count value

O(k), k 是元素个数

ltrim key start end

O(k), k 是元素个数

修改

lset key index value

O(n), n 是索引的偏移量

阻塞操作

blpop brpop

O(1)

list类型的应用场景

1、用list作为数组这样的结构来存储多个元素

2、生产消费模型

image.png
image.png

3、redis分频道阻塞消息队列模型

image.png
image.png
image.png
image.png
image.png
image.png

总结

本文详细介绍了 Redis 的 List(列表)数据类型,它是一个有序且允许元素重复的集合,底层实现为双端队列,保证了在头尾两端进行操作的效率。

我们探讨了 List 的核心操作命令,可以分为以下几类:

  1. 添加操作:lpush/rpush 用于从左侧或右侧插入一个或多个元素,linsert 可在指定元素前后插入新元素。
  2. 查找操作:lrange 用于获取指定范围内的元素,lindex 获取指定下标的元素,而 llen 则返回列表的长度,时间复杂度为 O(1)。
  3. 删除操作:lpop/rpop 分别从左侧或右侧移除一个元素,lrem 可以根据值删除指定数量的元素,ltrim 则通过保留指定范围内的元素来裁剪列表。
  4. 修改操作:lset 用于更新指定下标的元素值。
  5. 阻塞操作:blpop/brpop 是 lpop/rpop 的阻塞版本。当列表为空时,它们会阻塞客户端连接,直到有新元素可供弹出或超时,这使它们非常适合实现消息队列。

最后,我们介绍了 List 类型的典型应用场景,如作为普通数组存储数据,以及在生产者-消费者模型中充当高效、可靠的消息队列。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-08-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • lpush、lrange
  • lpushx、rpush、rpushx
  • lpop、rpop
  • lindex、linsert、llen
  • lerm
  • ltrim 、lset
  • blpop、brpop
  • 命令总结
  • list类型的应用场景
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档