redis----list详解
列表(List)相当于数组或者顺序表
一、通用命令
LPUSH key value1 [value2 ...]
- 在列表
key
的左侧(头部)插入一个或多个值。 - 示例:
LPUSH fruits apple banana
→ 列表变为[banana, apple]
- 在列表
LPUSHX
只有列表已存在时才会执行插入,若列表不存在则不进行任何操作
RPUSH key value1 [value2 ...]
- 在列表
key
的右侧(尾部)插入一个或多个值。 - 示例:
RPUSH fruits orange
→ 列表变为[banana, apple, orange]
- 在列表
RPUSHX
只有列表已存在时才会执行插入,若列表不存在则不进行任何操作
LPOP key
- 移除并返回列表
key
左侧的第一个元素。 - 示例:
LPOP fruits
→ 返回banana
,列表变为[apple, orange]
- 移除并返回列表
lpop后面有个count参数,表示要删删除几个元素
RPOP key
- 移除并返回列表
key
右侧的最后一个元素。 - 示例:
RPOP fruits
→ 返回orange
,列表变为[apple]
- 移除并返回列表
rpop后面有个count参数,表示要删删除几个元素
LRANGE key start stop
- 返回列表
key
中从索引start
到stop
的元素(包含两端)。 - 索引支持负数:
-1
表示最后一个元素,-2
表示倒数第二个,以此类推。 - 示例:
LRANGE fruits 0 -1
→ 返回列表所有元素
- 返回列表
当下标越界后,会尽可能的返回结果,返回区间内存在的元素
LLEN key
- 返回列表
key
的长度(元素个数)。 - 示例:
LLEN fruits
→ 返回当前列表长度
- 返回列表
LINDEX key index
- 返回列表
key
中索引为index
的元素。 - 示例:
LINDEX fruits 0
→ 返回列表第一个元素
- 返回列表
1.LINSERT
是用于在列表的指定元素前后插入新元素的命令,其语法如下:
LINSERT key BEFORE|AFTER pivot value
参数说明:
key
:列表的键名BEFORE|AFTER
:指定插入位置(在 pivot 元素之前或之后)pivot
:列表中已存在的参考元素value
:要插入的新元素
LSET key index value
- 将列表
key
中索引为index
的元素设置为value
。 - 示例:
LSET fruits 0 grape
→ 将第一个元素改为grape
- 将列表
LREM key count value
- 从列表
key
中删除count
个值为value
的元素。 count > 0
:从左侧开始删除;count < 0
:从右侧开始删除;count = 0
:删除所有。- 示例:
LREM fruits 2 apple
→ 从左侧删除 2 个apple
- 从列表
LTRIM key start stop
- 保留列表
key
中从start
到stop
的元素,删除其他元素(修剪列表)。 - 示例:
LTRIM fruits 0 1
→ 只保留前两个元素
- 保留列表
RPOPLPUSH source destination
- 从
source
列表右侧弹出元素,同时将其插入destination
列表左侧。 - 示例:
RPOPLPUSH fruits backups
→ 转移最后一个元素到backups
列表头部
- 从
5、BLPOP和BRPOP
在 Redis 中,BLPOP
和 BRPOP
是 阻塞式列表弹出命令,核心作用是从列表(List)的头部或尾部弹出元素;若列表为空,则命令会阻塞当前客户端,直到有元素可用或超时,常用于实现 消息队列、任务调度、分布式锁等待 等场景。
一、核心定义与语法
两者逻辑一致,仅弹出元素的位置不同:
BLPOP
(Block Left Pop):从列表 头部(左侧) 弹出元素,空列表时阻塞。BRPOP
(Block Right Pop):从列表 尾部(右侧) 弹出元素,空列表时阻塞。
1. 基本语法
BLPOP key [key ...] timeout
BRPOP key [key ...] timeout
参数说明:
参数 | 含义 |
---|---|
key [key...] | 1 个或多个列表键(支持同时监听多个列表,按顺序优先级处理)。 |
timeout | 阻塞超时时间(单位:秒): - 若 timeout=0 :永久阻塞,直到有元素弹出;- 若 timeout>0 :超时后返回 nil ,不阻塞。 |
2. 返回值
命令返回一个 二元数组,格式如下:
返回值结构 | 说明 |
---|---|
第一个元素 | 弹出元素所属的 列表键名(若监听多个键,需通过此值判断元素来源)。 |
第二个元素 | 从列表中弹出的 具体元素值。 |
超时返回 | 若超时且无元素,返回 nil 。 |
二、核心特性与差异
1. 共性:阻塞逻辑与优先级
无论 BLPOP
还是 BRPOP
,阻塞时均遵循以下规则:
- 空列表阻塞:若所有监听的列表均为空,客户端会进入 阻塞状态(不占用 CPU,Redis 会将其加入 “阻塞客户端队列”),不影响其他命令执行。
- 元素触发唤醒:当其他客户端向任一监听列表添加元素(如
LPUSH
/RPUSH
)时,Redis 会立即唤醒阻塞的客户端,执行弹出操作。 - 多键优先级:若同时监听多个列表(如
BLPOP list1 list2 0
),Redis 会 按键的顺序依次检查,仅从第一个非空列表中弹出元素(list1 优先级高于 list2)。 - 单元素原子性:即使多个客户端同时阻塞监听同一个列表,Redis 会保证 每个元素仅被一个客户端弹出(原子操作,无 “竞态问题”)。
2. 差异:弹出位置与典型场景
命令 | 弹出位置 | 典型使用场景 |
---|---|---|
BLPOP | 列表头部 | 1. 实现 “先进先出(FIFO)” 队列(配合 RPUSH 入队);2. 优先级队列(头部元素优先处理)。 |
BRPOP | 列表尾部 | 1. 实现 “后进先出(LIFO)” 栈(配合 RPUSH 入栈);2. 简单消息队列(尾部弹出避免头部阻塞)。 |
三、使用示例
假设存在两个列表 task_queue
(任务队列)和 urgent_queue
(紧急任务队列),用 BLPOP
优先处理紧急任务:
1. 列表为空时阻塞
执行命令(超时时间 30 秒):
BLPOP urgent_queue task_queue 30
此时两个列表均为空,客户端进入 阻塞状态,等待元素插入。
2. 其他客户端插入元素
另一个客户端向 urgent_queue
插入紧急任务:
RPUSH urgent_queue "fix_login_bug"
3. 阻塞客户端被唤醒并返回结果
原阻塞客户端立即被唤醒,返回以下结果(二元数组):
1) "urgent_queue" # 元素所属的键
2) "fix_login_bug" # 弹出的元素值
4. 超时无元素返回
若 30 秒内无任何客户端向 urgent_queue
或 task_queue
插入元素,命令超时返回 nil
:
(nil)
四、关键注意事项
阻塞仅影响当前客户端
阻塞期间,当前客户端无法执行其他命令,但 Redis 服务器仍可正常处理其他客户端的请求(非全局阻塞)。避免永久阻塞(timeout=0)的风险
若设置timeout=0
(永久阻塞),需确保有其他客户端会向监听列表插入元素;否则当前客户端会一直阻塞,需通过CLIENT KILL
命令强制关闭连接。键不存在的处理
若监听的键不存在(如BLPOP non_exist_key 5
),Redis 会将其视为 “空列表”,同样触发阻塞,直到键被创建并插入元素。与非阻塞命令的区别(LPOP/RPOP)
LPOP/RPOP
:列表为空时立即返回nil
,不阻塞;BLPOP/BRPOP
:列表为空时阻塞,适合需要 “等待元素” 的场景(如消息队列消费者)。
分布式场景的限制
若多个客户端同时阻塞监听同一个列表,Redis 会按 “先阻塞先唤醒” 的顺序分配元素(公平性保证),但不支持 “广播”(一个元素仅被一个客户端消费)。
五、典型应用场景
消息队列(MQ)
- 生产者:用
RPUSH
向列表尾部插入消息; - 消费者:用
BRPOP
阻塞监听列表,有消息时立即消费(避免轮询空列表,减少资源浪费)。
- 生产者:用
分布式任务调度
多个 worker 进程用BLPOP
监听同一个任务列表,Redis 自动将任务分配给空闲 worker(原子性弹出,避免重复处理)。分布式锁的 “等待重试”
当客户端获取锁失败时,用BLPOP
阻塞监听 “锁释放通知列表”,待持有锁的客户端释放锁后,通过LPUSH
通知等待客户端重试,减少轮询开销。