摘要
List 核心详解
- Redis List 是一个有序字符串列表,本质上是:
key -> List<String>
元素按插入顺序排列
允许重复元素
支持从 左(头) 和 右(尾) 两端操作
有序
可重复
双端操作(Deque)
支持阻塞读
元素类型为 String(二进制安全)
- Redis List 的理论最大长度为 2^32 - 1 = 4294967295,但实际业务中,元素数量 ≥ 10,000 就算 BigKey 了。
- List的底层是一个双向链表,对双端的操作性能很高,但是通过索引下标直接操作某一个中间节点时性能很差
- 常用数据结构
Stack(栈) = LPUSH + LPOP
Queue(队列)= LPUSH + RPOP
Blocking MQ(阻塞队列)= LPUSH + BRPOP
视频列表、签到列表
排队机
简化版的MQ
List 只用于 顺序消费
始终限制 List 长度(LTRIM)
避免中间插入、删除
大 List 删除使用 UNLINK
高可靠消息不要用 List
List 命令
- SpringBoot 的
RedisTemplate<K,V>.opsForList() 中 List 数据类型 的操作方法与 Redis 原生命令的对应关系如下:
区间访问与整体控制
| 方法功能 |
方法 |
Redis 原始命令 |
备注 |
| 获取指定区间元素 |
range(K key, long start, long end) |
LRANGE key start end |
end = -1 表示到末尾 |
| 裁剪 list,仅保留指定区间 |
trim(K key, long start, long end) |
LTRIM key start end |
原地修改 |
| 获取 list 长度 |
size(K key) |
LLEN key |
— |
- 📌 使用建议
LRANGE 0 -1 等价全量读取,小 list 可用
- 大 list 建议分页 + LRANGE
左侧入队(Head)
| 方法功能 |
方法 |
Redis 原始命令 |
备注 |
| 左侧插入一个元素 |
leftPush(K key, V value) |
LPUSH key value |
返回插入后长度 |
| 左侧批量插入 |
leftPushAll(K key, V... values) |
LPUSH key value [value ...] |
依次从左插入 |
| 左侧批量插入 |
leftPushAll(K key, Collection<V> values) |
LPUSH key value [value ...] |
— |
| key 存在时左侧插入 |
leftPushIfPresent(K key, V value) |
LPUSHX key value |
key 不存在不执行 |
| 在 pivot 左侧插入 |
leftPush(K key, V pivot, V value) |
LINSERT key BEFORE pivot value |
pivot 不存在返回 -1 |
右侧入队(Tail)
| 方法功能 |
方法 |
Redis 原始命令 |
备注 |
| 右侧插入一个元素 |
rightPush(K key, V value) |
RPUSH key value |
— |
| 右侧批量插入 |
rightPushAll(K key, V... values) |
RPUSH key value [value ...] |
— |
| 右侧批量插入 |
rightPushAll(K key, Collection<V> values) |
RPUSH key value [value ...] |
— |
| key 存在时右侧插入 |
rightPushIfPresent(K key, V value) |
RPUSHX key value |
— |
| 在 pivot 右侧插入 |
rightPush(K key, V pivot, V value) |
LINSERT key AFTER pivot value |
pivot 不存在返回 -1 |
非阻塞弹出
| 方法功能 |
方法 |
Redis 原始命令 |
备注 |
| 左侧弹出 |
leftPop(K key) |
LPOP key |
— |
| 左侧批量弹出 |
leftPop(K key, long count) |
LPOP key count |
Redis ≥ 6.2 |
| 右侧弹出 |
rightPop(K key) |
RPOP key |
— |
| 右侧批量弹出 |
rightPop(K key, long count) |
RPOP key count |
Redis ≥ 6.2 |
阻塞弹出(Blocking Queue)
| 方法功能 |
方法 |
Redis 原始命令 |
备注 |
| 左侧阻塞弹出 |
leftPop(K key, timeout) |
BLPOP key timeout |
队列为空时阻塞 |
| 右侧阻塞弹出 |
rightPop(K key, timeout) |
BRPOP key timeout |
— |
原子移动
Redis 6.2+ 新模型(统一、可读性更强)
| 方法功能 |
方法 |
Redis 原始命令 |
备注 |
| 原子移动(非阻塞) |
move(sourceKey, from, destinationKey, to) |
LMOVE source dest LEFT|RIGHT LEFT|RIGHT |
Redis ≥ 6.2 |
| 原子移动(阻塞) |
move(sourceKey, from, destinationKey, to, timeout) |
BLMOVE source dest LEFT|RIGHT LEFT|RIGHT timeout |
Redis ≥ 6.2 |
- 语义说明
- 从 sourceKey 的一端 POP
- 向 destinationKey 的一端 PUSH
- 整个过程 原子性保证
- 命令参数说明:
- source:源 List(从这里取一个元素)
- dest:目标 List(往这里放一个元素)
- 第一个 LEFT/RIGHT:从 source 的哪一端弹出元素
- 第二个 LEFT/RIGHT:从 dest 的哪一端插入元素
- timeout: 阻塞时间
- 当 source 为空(或不存在)时,客户端最多阻塞等待 timeout 秒,直到有元素可被移动,或等待超时。
- timeout = 0:无限期阻塞,直到有数据可用或连接断开
旧命令(即将废弃)
| 方法功能 |
方法 |
Redis 原始命令 |
推荐替代 |
| 右弹左插 |
rightPopAndLeftPush(...) |
RPOPLPUSH |
LMOVE |
| 阻塞右弹左插 |
rightPopAndLeftPush(..., timeout) |
BRPOPLPUSH |
BLMOVE |
随机访问与定位(O(N))
| 方法功能 |
方法 |
Redis 原始命令 |
备注 |
| 获取第一个元素 |
getFirst(K key) |
LINDEX key 0 |
O(N) |
| 获取最后一个元素 |
getLast(K key) |
LINDEX key -1 |
O(N) |
| 获取指定索引元素 |
index(K key, long index) |
LINDEX key index |
O(N) |
⚠️ 注意: List 不是数组,随机访问是线性扫描,不适合频繁随机读取
搜索与删除
| 方法功能 |
方法 |
Redis 原始命令 |
备注 |
| 删除指定值 |
remove(K key, long count, Object value) |
LREM key count value |
count ≥0 从左,<0 从右 |
| 获取首次出现位置 |
indexOf(K key, V value) |
LPOS key value |
Redis ≥ 6.0 |
| 获取最后出现位置 |
lastIndexOf(K key, V value) |
LPOS key value RANK -1 |
Redis ≥ 6.0 |
List 的典型使用模式总结
| 场景 |
推荐方式 |
| 队列(FIFO) |
RPUSH + LPOP |
| 栈(LIFO) |
LPUSH + LPOP |
| 阻塞队列 |
BLPOP / BRPOP |
| 可靠队列 |
LMOVE / BLMOVE |
| 消息转移 |
LMOVE source dest |
所有评论(0)