Redis 列表 List
List 是元素有序可重复的双向链表结构,头尾操作都是 O(1)。经典用途有两个:左侧写入、右侧消费的「消息队列」,以及最新动态的「时间线」展示。
头尾写入
LPUSH 从头部压入,RPUSH 从尾部追加,返回值是当前长度:
LPUSH mylist a b c
# 输出:(integer) 3
# 顺序:[c, b, a]
RPUSH mylist d e
# 输出:(integer) 5
# 顺序:[c, b, a, d, e]
注意 LPUSH 一次多个时按参数顺序逐个压入,c 在参数里最后却被放到最前。
读取范围
LRANGE 取区间元素(含两端),负数表示从尾部倒数:
LRANGE mylist 0 -1
# 输出:1) "c" 2) "b" 3) "a" 4) "d" 5) "e"
LRANGE mylist 0 1
# 输出:1) "c" 2) "b"
LRANGE mylist -2 -1
# 输出:1) "d" 2) "e"
LRANGE 0 -1 即全量取出,列表很长时是 O(N) 操作,慎用。
弹出元素
LPOP/RPOP 弹出并删除头部/尾部元素:
LPOP mylist
# 输出:"c"
RPOP mylist
# 输出:"e"
LLEN mylist
# 输出:(integer) 3
空列表时 LPOP 返回 nil,不会报错。
阻塞弹出
BLPOP/BRPOP 在列表为空时阻塞等待,带超时秒数,是队列消费端的标准写法:
BLPOP mylist 5
# 输出:1) "mylist" 2) "b" # 5 秒内有数据立刻弹出
BRPOP mylist 0 # 0 表示一直等待
模拟消息队列
生产者 RPUSH 入队、消费者 BLPOP 出队即可搭一个最简队列:
# 终端 A:生产者
redis-cli RPUSH task:queue job1 job2
# 输出:(integer) 2
# 终端 B:消费者
redis-cli BLPOP task:queue 0
# 输出:1) "task:queue" 2) "job1"
List 队列消费即删除、无确认机制,可靠投递需求应改用 Stream(见第 17 章)。
截断与封顶
LTRIM 只保留指定区间,可给「无限增长」的列表封顶:
RPUSH log:list 1 2 3 4 5
LTRIM log:list 0 99 # 只留前 100 条,超出丢弃
LTRIM log:list 0 1 # 示例:只留前 2 条
LRANGE log:list 0 -1
# 输出:1) "1" 2) "2"
易踩坑
- 别把 List 当无界队列:只进不出会持续占内存,用 LTRIM 封顶或用 Stream 落地;
- LPUSH 后再 LRANGE 0 -1 的顺序与直觉相反,先想清头尾;
- LINDEX 按索引取中间元素是 O(N),频繁随机访问应换 Hash 或 ZSet。
小结
List 靠 LPUSH/RPUSH + LRANGE 展示时间线,靠 LPUSH/RPOP 或阻塞版 BLPOP 搭轻量队列。凡用列表务必设好上限或消费机制,避免内存无限增长。