Redis 命令及数据类型 -- List
摘要
- 本文介绍 Redis List 数据类型
- 本文基于
redis-7.4.7,springboot-3.5.8 - Redis官网:https://redis.io/
- Redis 命令文档:https://redis.io/docs/latest/commands/
List 核心详解
-
Redis List 是一个有序字符串列表,本质上是:
1 | key -> List<String> |
-
List 的核心特性
1 | 有序 |
-
Redis List 的理论最大长度为 2^32 - 1 = 4294967295,但实际业务中,元素数量 ≥ 10,000 就算 BigKey 了。
-
List的底层是一个双向链表,对双端的操作性能很高,但是通过索引下标直接操作某一个中间节点时性能很差
-
常用数据结构
1 | Stack(栈) = LPUSH + LPOP |
-
List 的使用场景
1 | 视频列表、签到列表 |
-
生产环境建议
1 | 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 |