Redis 命令及数据类型 -- List

摘要

List 核心详解

  • Redis List 是一个有序字符串列表,本质上是:

1
2
3
4
5
key -> List<String>
# 说明
元素按插入顺序排列
允许重复元素
支持从 左(头) 和 右(尾) 两端操作
  • List 的核心特性

1
2
3
4
5
有序
可重复
双端操作(Deque)
支持阻塞读
元素类型为 String(二进制安全)
  • Redis List 的理论最大长度为 2^32 - 1 = 4294967295,但实际业务中,元素数量 ≥ 10,000 就算 BigKey 了。

  • List的底层是一个双向链表,对双端的操作性能很高,但是通过索引下标直接操作某一个中间节点时性能很差

  • 常用数据结构

1
2
3
Stack(栈) = LPUSH + LPOP
Queue(队列)= LPUSH + RPOP
Blocking MQ(阻塞队列)= LPUSH + BRPOP
  • List 的使用场景

1
2
3
视频列表、签到列表
排队机
简化版的MQ
  • 生产环境建议

1
2
3
4
5
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