Redis列表
列表(List)是有序、可重复的字符串集合,基于双向链表实现,支持两端高效插入和弹出。
结构概述
基本特点
Bash
- 有序字符串集合
- 元素可重复
- 双向链表结构
- 两端操作高效O(1)
- 单个列表最多2^32-1个元素
结构示意
Bash
列表头部 ← → 列表尾部
[a] ← [b] ← [c] ← [d] ← [e]
LPUSH从左侧插入,LPOP从左侧弹出
RPUSH从右侧插入,RPOP从右侧弹出
内部编码
ziplist编码
Bash
触发条件:
- 元素数量 ≤ list-max-ziplist-size(默认-2,约512)
- 单个元素大小 ≤ 64字节
特点:
- 紧凑连续内存
- 内存效率高
- 适合小规模列表
linkedlist编码
Bash
触发条件:
- 元素数量超过阈值
- 或元素大小超过限制
特点:
- 双向链表结构
- 每个节点独立内存分配
- 指针连接节点
- 内存占用较大
quicklist编码
Bash
Redis 3.2+默认编码:
- ziplist组成的双向链表
- 兼顾内存效率和操作效率
- 每个节点是一个ziplist
查看编码
Bash
LPUSH mylist a b c
OBJECT ENCODING mylist
# 返回: "quicklist"(Redis 3.2+)
quicklist详解
结构原理
Bash
quicklist = linkedlist + ziplist
┌──ziplist──┐ ← ┌──ziplist──┐ ← ┌──ziplist──┐
│a,b,c,d,e,f│ │g,h,i,j,k │ │l,m,n,o │
└──┬───────┬─┘ └─┬───────┬─┘ └─┬───────┬─┘
prev next prev next prev next
配置参数
Bash
# 每个ziplist的最大元素数
list-max-ziplist-size -2
# -2表示ziplist最大8KB
# 中间节点压缩
list-compress-depth 0
# 0表示不压缩,1表示保留首尾各1个节点不压缩
应用场景
1. 消息队列
Bash
# 生产者:从右侧推入
RPUSH queue:orders "order_data"
# 消费者:从左侧弹出
LPOP queue:orders
# 阻塞弹出(等待消息)
BLPOP queue:orders 30
2. 最新列表
Bash
# 添加最新文章(从左侧)
LPUSH articles:latest "article:1001"
# 限制列表长度(保留10个)
LTRIM articles:latest 0 9
# 获取最新文章
LRANGE articles:latest 0 9
3. 时间线/朋友圈
text
# 用户发布动态
LPUSH timeline:user:1000 "post:500"
# 获取用户时间线
LRANGE timeline:user:1000 0 20
# 关注的用户动态合并
LPUSH timeline:home "post:501"
4. 栈实现
text
# 入栈(同一端操作)
LPUSH stack "item1"
LPUSH stack "item2"
# 出栈
LPOP stack
# 返回: "item2"(后进先出)
5. 队列实现
text
# 入队(右端)
RPUSH queue "task1"
# 出队(左端)
LPOP queue
# 先进先出
与Set对比
| 特性 | List | Set |
|---|---|---|
| 顺序 | 有序 | 无序 |
| 重复 | 允许 | 不允许 |
| 索引访问 | 支持 | 不支持 |
| 两端操作 | 支持 | 不支持 |
| 集合运算 | 不支持 | 支持 |
操作特点
O(1)操作
text
LPUSH/RPUSH:两端插入
LPOP/RPOP:两端弹出
LLEN:获取长度
O(N)操作
text
LRANGE:获取范围元素
LINDEX:获取指定索引元素
LSET:设置指定索引元素
LINSERT:插入元素
LREM:删除元素
# N为列表长度或操作范围
阻塞操作
text
# 阻塞弹出
BLPOP queue 10 # 阻塞10秒
BRPOP queue 0 # 无限等待
# 阻塞移动
BRPOPLPUSH src dest 10
性能建议
两端优先
text
- 尽量使用LPUSH/RPUSH/LPOP/RPOP
- 避免频繁使用LINDEX/LSET(中间元素)
- 两端操作O(1),中间操作O(N)
控制长度
text
# 使用LTRIM限制长度
LPUSH timeline "new_item"
LTRIM timeline 0 1000
# 保持列表最多1001个元素
批量操作
text
# 批量插入
LPUSH mylist a b c d e
# 比多次单独LPUSH效率高
注意事项
内存占用
text
- 每个元素独立存储(linkedlist)
- quicklist优化内存
- 大列表占用较多内存
阻塞风险
text
- LRANGE获取大量元素可能阻塞
- 使用小范围或分批获取
- HGETALL同理
索引范围
text
索引从0开始
负索引从末尾计算(-1为最后)
索引超出范围返回nil或报错
编码对比
| 编码 | 条件 | 内存效率 | 操作效率 |
|---|---|---|---|
| ziplist | 小数据 | 高 | 两端高效 |
| linkedlist | 大数据 | 中 | 两端高效 |
| quicklist | 混合 | 中高 | 两端高效 |
要点总结
- 列表是双向链表,有序可重复,两端操作O(1)
- Redis 3.2+默认使用quicklist编码(ziplist+linkedlist)
- 应用场景:消息队列、最新列表、时间线、栈/队列
- LPUSH/RPUSH插入,LPOP/RPOP弹出,LRANGE获取范围
- 避免频繁操作中间元素,两端优先
- LTRIM控制列表长度,避免无限增长
- BLPOP/BRPOP阻塞弹出,实现可靠消费者
- quicklist配置list-max-ziplist-size优化内存
📝 发现内容有误?点击此处直接编辑