Redis列表List #
一、列表概述 #
1.1 什么是列表 #
Redis列表是简单的字符串列表,按照插入顺序排序:
- 有序:元素按插入顺序排列
- 可重复:允许重复元素
- 双端操作:可以从两端插入和弹出
text
列表结构:
┌─────────────────────────────────────────────┐
│ LPUSH ← [元素1, 元素2, 元素3, 元素4] → RPUSH │
│ │
│ LPOP ← [元素1, 元素2, 元素3, 元素4] → RPOP │
└─────────────────────────────────────────────┘
特点:
- 最大长度:2^32 - 1(约40亿)
- 底层实现:quicklist(双向链表 + listpack)
1.2 列表编码 #
text
Redis列表的编码方式:
1. listpack(压缩列表)
┌─────────────────────────────────────────────┐
│ 元素数量少时使用 │
│ 内存连续,效率高 │
│ 条件:元素数<512,单元素<64字节 │
└─────────────────────────────────────────────┘
2. quicklist(快速列表)
┌─────────────────────────────────────────────┐
│ 双向链表 + listpack节点 │
│ 兼顾内存和性能 │
│ 大列表使用 │
└─────────────────────────────────────────────┘
二、基本操作 #
2.1 插入元素 #
bash
# LPUSH: 从左侧插入
LPUSH mylist "world"
# (integer) 1
LPUSH mylist "hello"
# (integer) 2
# 列表内容:["hello", "world"]
# RPUSH: 从右侧插入
RPUSH mylist "redis"
# (integer) 3
# 列表内容:["hello", "world", "redis"]
# 批量插入
LPUSH mylist "a" "b" "c"
# (integer) 6
RPUSH mylist "x" "y" "z"
# (integer) 9
# LPUSHX: 键存在时从左侧插入
LPUSHX mylist "first"
# (integer) 10
LPUSHX notexist "value"
# (integer) 0 键不存在,不插入
# RPUSHX: 键存在时从右侧插入
RPUSHX mylist "last"
# (integer) 11
2.2 弹出元素 #
bash
# LPOP: 从左侧弹出
LPOP mylist
# "c"
# RPOP: 从右侧弹出
RPOP mylist
# "z"
# 弹出多个元素(Redis 6.2+)
LPOP mylist 2
# 1) "b"
# 2) "a"
RPOP mylist 2
# 1) "y"
# 2) "x"
# 列表为空时
LPOP emptylist
# (nil)
2.3 查看列表 #
bash
# LRANGE: 获取范围内的元素
LPUSH mylist "a" "b" "c" "d" "e"
# 获取所有元素
LRANGE mylist 0 -1
# 1) "e"
# 2) "d"
# 3) "c"
# 4) "b"
# 5) "a"
# 获取前3个元素
LRANGE mylist 0 2
# 1) "e"
# 2) "d"
# 3) "c"
# 获取最后2个元素
LRANGE mylist -2 -1
# 1) "b"
# 2) "a"
# LLEN: 获取列表长度
LLEN mylist
# (integer) 5
# LINDEX: 获取指定位置元素
LINDEX mylist 0
# "e"
LINDEX mylist -1
# "a"
LINDEX mylist 10
# (nil) 索引超出范围
三、修改操作 #
3.1 设置元素 #
bash
# LSET: 设置指定位置的元素
LPUSH mylist "a" "b" "c"
LSET mylist 0 "x"
# OK
LRANGE mylist 0 -1
# 1) "x"
# 2) "b"
# 3) "a"
# 索引超出范围
LSET mylist 10 "y"
# (error) ERR index out of range
3.2 插入元素 #
bash
# LINSERT: 在指定元素前后插入
LPUSH mylist "a" "b" "c"
# 在"b"前插入
LINSERT mylist BEFORE "b" "x"
# (integer) 4
LRANGE mylist 0 -1
# 1) "c"
# 2) "x"
# 3) "b"
# 4) "a"
# 在"b"后插入
LINSERT mylist AFTER "b" "y"
# (integer) 5
LRANGE mylist 0 -1
# 1) "c"
# 2) "x"
# 3) "b"
# 4) "y"
# 5) "a"
# 元素不存在
LINSERT mylist BEFORE "notexist" "z"
# (integer) -1
3.3 删除元素 #
bash
# LREM: 删除指定元素
LPUSH mylist "a" "b" "a" "c" "a"
# 删除2个"a"(从头开始)
LREM mylist 2 "a"
# (integer) 2
LRANGE mylist 0 -1
# 1) "c"
# 2) "a"
# 3) "b"
# 删除所有"a"
LPUSH mylist "a" "a"
LREM mylist 0 "a"
# (integer) 3
# 删除1个"b"(从尾开始,负数)
LPUSH mylist "b" "b" "b"
LREM mylist -2 "b"
# (integer) 2
3.4 裁剪列表 #
bash
# LTRIM: 保留指定范围的元素
LPUSH mylist "a" "b" "c" "d" "e"
LTRIM mylist 0 2
# OK
LRANGE mylist 0 -1
# 1) "e"
# 2) "d"
# 3) "c"
# 保留最后3个元素
LPUSH mylist "f" "g"
LTRIM mylist -3 -1
# OK
LRANGE mylist 0 -1
# 1) "d"
# 2) "c"
# 3) "g"
四、阻塞操作 #
4.1 阻塞弹出 #
bash
# BLPOP: 阻塞式左侧弹出
# 语法:BLPOP key [key ...] timeout
# 列表有元素时立即返回
LPUSH mylist "a" "b"
BLPOP mylist 0
# 1) "mylist"
# 2) "b"
# 列表为空时阻塞等待
BLPOP emptylist 10
# 等待10秒,如果期间有元素插入则返回
# 1) "emptylist"
# 2) "value"
# 超时返回
BLPOP emptylist 5
# (nil)
# (5.10s)
# BRPOP: 阻塞式右侧弹出
RPUSH mylist "a" "b"
BRPOP mylist 0
# 1) "mylist"
# 2) "b"
# 同时监听多个列表
BLPOP list1 list2 list3 10
# 返回第一个有元素的列表
4.2 阻塞操作应用 #
bash
# 消息队列消费者
# 消费者1
BLPOP queue:task 0
# 阻塞等待任务
# 消费者2
BLPOP queue:task 0
# 阻塞等待任务
# 生产者
LPUSH queue:task "task_data"
# 消费者1收到任务
五、列表间操作 #
5.1 元素移动 #
bash
# RPOPLPUSH: 从一个列表右侧弹出,推入另一个列表左侧
LPUSH list1 "a" "b" "c"
RPOPLPUSH list1 list2
# "a"
LRANGE list1 0 -1
# 1) "c"
# 2) "b"
LRANGE list2 0 -1
# 1) "a"
# BRPOPLPUSH: 阻塞式移动
BRPOPLPUSH list1 list2 10
# 从list1右侧弹出,推入list2左侧
# 如果list1为空,阻塞等待
5.2 循环队列 #
bash
# 使用RPOPLPUSH实现循环队列
# 处理元素后放回队列尾部
# 获取任务
RPOPLPUSH queue:task queue:processing
# 处理任务...
# 成功:从processing删除
LREM queue:processing 1 "task_data"
# 失败:放回队列
RPOPLPUSH queue:processing queue:task
六、应用场景 #
6.1 消息队列 #
bash
# 简单队列
# 生产者
LPUSH queue:email "email_data_1"
LPUSH queue:email "email_data_2"
# 消费者
RPOP queue:email
# "email_data_1"
# 可靠队列(使用备份队列)
RPOPLPUSH queue:email queue:email:processing
# 处理完成后删除
LREM queue:email:processing 1 "email_data_1"
6.2 最新列表 #
bash
# 最新文章列表
LPUSH articles:latest "article:1001"
LPUSH articles:latest "article:1002"
LPUSH articles:latest "article:1003"
# 只保留最新10篇
LTRIM articles:latest 0 9
# 获取最新5篇
LRANGE articles:latest 0 4
# 1) "article:1003"
# 2) "article:1002"
# 3) "article:1001"
6.3 时间线 #
bash
# 用户时间线
LPUSH timeline:user:1001 "post:2001"
LPUSH timeline:user:1001 "post:2002"
LPUSH timeline:user:1001 "post:2003"
# 获取时间线
LRANGE timeline:user:1001 0 9
6.4 分页 #
bash
# 分页获取列表
# 每页10条,第1页
LRANGE mylist 0 9
# 第2页
LRANGE mylist 10 19
# 第N页
# start = (page - 1) * pageSize
# end = page * pageSize - 1
七、性能优化 #
7.1 避免大列表 #
bash
# 不推荐:无限增长的列表
LPUSH huge:list "item"
# 推荐:限制列表长度
LPUSH limited:list "item"
LTRIM limited:list 0 999 # 只保留1000个
7.2 批量操作 #
bash
# 不推荐:多次单操作
LPUSH mylist "a"
LPUSH mylist "b"
LPUSH mylist "c"
# 推荐:批量操作
LPUSH mylist "a" "b" "c"
7.3 使用阻塞操作 #
bash
# 不推荐:轮询
while true; do
result=$(RPOP queue)
if [ -n "$result" ]; then
process "$result"
fi
sleep 1
done
# 推荐:阻塞弹出
while true; do
result=$(BRPOP queue 0)
process "$result"
done
八、总结 #
列表操作命令:
| 命令 | 说明 |
|---|---|
| LPUSH | 左侧插入 |
| RPUSH | 右侧插入 |
| LPOP | 左侧弹出 |
| RPOP | 右侧弹出 |
| LRANGE | 获取范围 |
| LLEN | 获取长度 |
| LINDEX | 获取指定位置 |
| LSET | 设置指定位置 |
| LREM | 删除元素 |
| LTRIM | 裁剪列表 |
阻塞命令:
| 命令 | 说明 |
|---|---|
| BLPOP | 阻塞左侧弹出 |
| BRPOP | 阻塞右侧弹出 |
| BRPOPLPUSH | 阻塞移动 |
应用场景:
| 场景 | 实现方式 |
|---|---|
| 消息队列 | LPUSH + BRPOP |
| 最新列表 | LPUSH + LTRIM |
| 时间线 | LPUSH + LRANGE |
| 分页 | LRANGE |
下一步,让我们学习Redis集合Set!
最后更新:2026-03-27