Redis 列表(上)

列表是有序可重复的字符串列表,本课学习列表的基本操作。

什么是列表?

列表类似于编程语言中的:

Redis列表的特点:

mylist
├─ "element1"
├─ "element2"
├─ "element3"
└─ "element4"
💡 底层实现: Redis列表使用快速列表(quicklist),是双向链表和压缩列表的组合,兼顾内存和性能。

LPUSH和RPUSH:插入元素

LPUSH:从左侧(头部)插入

REDIS
# 从左侧插入单个元素
LPUSH mylist "world"
(integer) 1  # 返回列表长度

# 从左侧插入多个元素
LPUSH mylist "hello"
(integer) 2

# 查看列表
LRANGE mylist 0 -1
1) "hello"
2) "world"
⚠️ 注意: LPUSH插入多个元素时,按参数顺序依次插入左侧。LPUSH mylist a b c 的结果是 [c, b, a, ...]

RPUSH:从右侧(尾部)插入

REDIS
# 从右侧插入
RPUSH mylist "Redis"
(integer) 3

RPUSH mylist "Tutorial"
(integer) 4

# 查看列表
LRANGE mylist 0 -1
1) "hello"
2) "world"
3) "Redis"
4) "Tutorial"

LPUSHX和RPUSHX:仅当列表存在时插入

REDIS
# 列表不存在时插入失败
LPUSHX notexist "value"
(integer) 0

# 列表存在时插入成功
LPUSHX mylist "first"
(integer) 5

RPUSHX mylist "last"
(integer) 6

LPOP和RPOP:弹出元素

LPOP:从左侧(头部)弹出

REDIS
# 查看当前列表
LRANGE mylist 0 -1
1) "first"
2) "hello"
3) "world"
4) "Redis"
5) "Tutorial"
6) "last"

# 从左侧弹出
LPOP mylist
"first"

# 弹出多个元素(Redis 6.2+)
LPOP mylist 2
1) "hello"
2) "world"

RPOP:从右侧(尾部)弹出

REDIS
# 从右侧弹出
RPOP mylist
"last"

# 弹出多个元素(Redis 6.2+)
RPOP mylist 2
1) "Tutorial"
2) "Redis"

列表为空时

REDIS
LPOP emptylist
(nil)  # 列表为空返回nil

LLEN:获取列表长度

REDIS
LPUSH mylist "a" "b" "c"
LLEN mylist
(integer) 3

# 列表不存在
LLEN notexist
(integer) 0

LRANGE:获取范围内的元素

LRANGE是最常用的列表查询命令。

基本用法

REDIS
LPUSH mylist "one" "two" "three" "four" "five"

# 获取所有元素
LRANGE mylist 0 -1
1) "five"
2) "four"
3) "three"
4) "two"
5) "one"

# 获取前3个元素
LRANGE mylist 0 2
1) "five"
2) "four"
3) "three"

# 获取最后2个元素
LRANGE mylist -2 -1
1) "two"
2) "one"

# 获取第2到第4个元素
LRANGE mylist 1 3
1) "four"
2) "three"
3) "two"

索引规则

索引 说明
0 第一个元素
1 第二个元素
-1 最后一个元素
-2 倒数第二个元素
0 -1 所有元素
⚠️ 注意: LRANGE的结束索引是包含的。LRANGE 0 2 返回索引0、1、2的元素(共3个)。

列表实现队列和栈

队列(FIFO:先进先出)

使用 RPUSH + LPOP 实现:

REDIS
# 生产者:从右侧入队
RPUSH queue:task "task1"
RPUSH queue:task "task2"
RPUSH queue:task "task3"

# 消费者:从左侧出队
LPOP queue:task
"task1"

LPOP queue:task
"task2"
入队 → [task1, task2, task3] → 出队
         RPUSH              LPOP

栈(LIFO:后进先出)

使用 LPUSH + LPOP 实现:

REDIS
# 入栈
LPUSH stack:data "item1"
LPUSH stack:data "item2"
LPUSH stack:data "item3"

# 出栈
LPOP stack:data
"item3"

LPOP stack:data
"item2"
入栈 → [item3, item2, item1] → 出栈
         LPUSH              LPOP
💡 记忆技巧:

  • 队列:RPUSH + LPOP(右进左出)
  • 栈:LPUSH + LPOP(左进左出)

阻塞式弹出:BLPOP和BRPOP

当列表为空时,BLPOP和BRPOP会阻塞等待,直到有元素或超时。

BLPOP:阻塞式左侧弹出

REDIS
# 客户端1:等待队列中的任务(最多等待10秒)
BLPOP queue:task 10

# 客户端2:添加任务
RPUSH queue:task "new_task"

# 客户端1收到:
1) "queue:task"  # 列表名
2) "new_task"    # 弹出的元素

BRPOP:阻塞式右侧弹出

REDIS
BRPOP queue:task 10

阻塞多个列表

REDIS
# 同时等待多个列表,哪个有数据就返回
BLPOP queue:high queue:low 10
💡 用途: BLPOP/BRPOP常用于实现任务队列、消息队列,消费者可以阻塞等待新任务。

列表应用场景

场景1:消息队列

REDIS
# 生产者:发送消息
RPUSH queue:email '{"to":"user@example.com","subject":"Hello"}'

# 消费者:接收消息(阻塞等待)
BLPOP queue:email 0

场景2:最新列表

REDIS
# 添加最新文章
LPUSH articles:latest "article:123"
LPUSH articles:latest "article:124"
LPUSH articles:latest "article:125"

# 获取最新10篇文章
LRANGE articles:latest 0 9

# 保持列表最多100篇文章
LTRIM articles:latest 0 99

场景3:时间线

REDIS
# 发布动态(添加到用户时间线)
LPUSH timeline:user:1 "post:1001"
LPUSH timeline:user:1 "post:1002"

# 查看时间线(最新20条)
LRANGE timeline:user:1 0 19

场景4:操作日志

REDIS
# 记录用户操作
RPUSH log:user:1 "login at 2026-06-23 10:00:00"
RPUSH log:user:1 "view article:123"
RPUSH log:user:1 "like article:123"

# 查看最近操作
LRANGE log:user:1 -10 -1

LTRIM:裁剪列表

LTRIM保留指定范围内的元素,删除其他元素。

REDIS
LPUSH mylist "one" "two" "three" "four" "five"

# 只保留前3个元素
LTRIM mylist 0 2
OK

LRANGE mylist 0 -1
1) "five"
2) "four"
3) "three"

应用:保持固定大小的列表

REDIS
# 添加新文章并保持最多100篇
LPUSH articles:latest "article:new"
LTRIM articles:latest 0 99
💡 技巧: LPUSH + LTRIM 组合使用,可以维护一个固定大小的最新列表。

❓ 常见问题

Q 列表最大能存储多少元素?
A 最多2^32 - 1个(约42亿),但实际受内存限制。
Q LPUSH和RPUSH的性能如何?
A O(1)时间复杂度,非常快。列表头尾操作都是常数时间。
Q LRANGE的性能如何?
A O(N),N是返回的元素数量。获取大量元素会较慢。
Q BLPOP会一直阻塞吗?
A 不会。设置超时时间,超时后返回nil。超时为0表示永久等待。
Q 列表中间插入元素?
A 使用LINSERT命令,但性能较差O(N)。建议只在头尾操作。

📖 小节

📝 作业

  1. 队列实现: 使用RPUSH和LPOP实现一个任务队列,模拟生产者和消费者
  2. 栈实现: 使用LPUSH和LPOP实现一个栈,模拟入栈和出栈
  3. 最新列表: 实现一个最新文章列表,添加文章并保持最多10篇
  4. 阻塞等待: 使用BLPOP实现一个阻塞式任务队列(需要两个终端)

下一课

下一课我们将学习 Redis 列表(下),学习列表的查询、修改和高级操作。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏