上一篇我们详细拆解了Redis键过期时间(TTL)的设置、查看与自动删除策略,掌握了缓存数据时效性管控与内存优化的核心方法。而作为Redis最基础且实用的数据结构,List(列表)凭借**有序、可重复、双端操作**的特性,成为消息队列、任务队列、时间线展示、分页查询等场景的首选方案。
本篇从Redis List的核心特性、常用命令、代码实战到生产落地场景,全方位讲解从基础入队出队到高级范围查询的全流程操作,帮你快速掌握List用法并落地业务。
核心定位:Redis List是基于双向链表实现的有序字符串列表,支持双端增删、范围查找,天然适配队列、栈、分页展示等业务,轻量易用且性能极高。
一、Redis List 核心特性与底层原理
Redis List以**双向链表**为底层结构,这也决定了它的核心特性,直接影响操作效率和业务选型:
- 有序性:元素按插入顺序排列,可通过下标精准定位,排序规则固定不变
- 可重复性:允许存储多个相同的元素,无去重机制
- 双端操作:支持从列表左侧(头)、右侧(尾)快速增删元素,时间复杂度O(1)
- 范围查询:可通过下标区间获取元素,时间复杂度O(N)(N为查询长度)
- 阻塞特性:提供阻塞出队命令,适配消费者队列场景,避免空轮询
关键提示:List整体查询效率较低,禁止用于海量数据的随机查找;双端操作极快,优先做队列、栈类业务。
二、Redis List 基础命令实战(命令行+Java代码)
List操作核心围绕入队(添加)、出队(删除)、查询、修改四大类,命令简洁直观,分为原生命令和SpringBoot RedisTemplate代码两种实现方式。
1. 元素入队:双端添加(左推/右推)
入队是List最基础的操作,支持从头部(LEFT)、尾部(RIGHT)批量添加元素,是实现队列、栈的基础。
| 命令 | 作用 | 示例 |
|---|---|---|
LPUSH key value1 value2... | 从列表左侧(头部)推入元素 | LPUSH msg:queue "hello" "redis" |
RPUSH key value1 value2... | 从列表右侧(尾部)推入元素 | RPUSH task:list "task1" "task2" |
// 左侧推入元素(栈模式)
public void leftPush(String key, String value) {
redisTemplate.opsForList().leftPush(key, value);
}
// 右侧推入元素(队列模式)
public void rightPush(String key, String value) {
redisTemplate.opsForList().rightPush(key, value);
}
// 批量右侧推入
public void rightPushAll(String key, List<String> values) {
redisTemplate.opsForList().rightPushAll(key, values);
}
2. 元素出队:双端删除(左弹/右弹)
出队操作会删除并返回列表元素,分为普通出队和阻塞出队,普通出队无元素时返回null。
| 命令 | 作用 | 示例 |
|---|---|---|
LPOP key | 从列表左侧(头部)弹出元素 | LPOP msg:queue |
RPOP key | 从列表右侧(尾部)弹出元素 | RPOP task:list |
// 左侧弹出元素
public String leftPop(String key) {
return redisTemplate.opsForList().leftPop(key);
}
// 右侧弹出元素
public String rightPop(String key) {
return redisTemplate.opsForList().rightPop(key);
}
3. 阻塞出队:消费者队列专用
阻塞出队是List的核心特性,列表为空时,客户端会阻塞等待,直到有元素入队或超时,彻底避免CPU空轮询。
| 命令 | 作用 | 示例 |
|---|---|---|
BLPOP key timeout | 阻塞左侧弹出,timeout为超时时间(秒) | BLPOP msg:queue 5 |
BRPOP key timeout | 阻塞右侧弹出,超时返回null | BRPOP task:list 10 |
// 阻塞右侧弹出,超时10秒
public String blockRightPop(String key) {
return redisTemplate.opsForList().rightPop(key, 10, TimeUnit.SECONDS);
}
4. 范围查询与长度统计
范围查询用于分页、列表展示场景,长度统计用于判断队列积压、列表元素数量。
| 命令 | 作用 | 示例 |
|---|---|---|
LRANGE key start end | 查询下标[start,end]区间的元素,end=-1表示末尾 | LRANGE blog:list 0 9(查询前10条) |
LINDEX key index | 获取指定下标的单个元素 | LINDEX msg:queue 0(获取头部元素) |
LLEN key | 获取列表长度(元素个数) | LLEN task:list |
// 范围查询:获取前10条数据
public List<String> rangeQuery(String key) {
// start=0,end=9 代表查询第1到第10个元素
return redisTemplate.opsForList().range(key, 0, 9);
}
// 查询指定下标元素
public String getByIndex(String key, long index) {
return redisTemplate.opsForList().index(key, index);
}
// 获取列表长度
public Long getListSize(String key) {
return redisTemplate.opsForList().size(key);
}
5. 高级操作:修改、截取与删除
LSET key index value:修改指定下标的元素值LTRIM key start end:截取列表,仅保留[start,end]区间元素,用于列表裁剪LREM key count value:删除指定元素,count>0从左删count个,count<0从右删|count|个,count=0删全部
// 截取列表,仅保留前100条
public void trimList(String key) {
redisTemplate.opsForList().trim(key, 0, 99);
}
// 删除指定元素
public void removeElement(String key, long count, String value) {
redisTemplate.opsForList().remove(key, count, value);
}
三、Redis List 经典业务场景落地
场景1:轻量级消息队列(生产者-消费者模型)
利用RPUSH+BRPOP实现简单可靠的消息队列,无需部署专业MQ,适合非核心异步业务。
// 生产者:消息入队
public void sendMsg(String queueKey, String msg) {
redisTemplate.opsForList().rightPush(queueKey, msg);
}
// 消费者:阻塞监听消息(后台线程)
@Async
public void consumerMsg(String queueKey) {
while (true) {
// 阻塞5秒,避免空轮询
String msg = redisTemplate.opsForList().rightPop(queueKey, 5, TimeUnit.SECONDS);
if (StringUtils.isNotBlank(msg)) {
// 处理业务逻辑
handleMsg(msg);
}
}
}
场景2:栈结构(先进后出)
利用LPUSH+LPOP实现栈结构,适配撤销操作、历史记录回溯等场景。
场景3:分页列表/时间线展示
利用LRANGE实现朋友圈、博客、评论列表的分页查询,配合LTRIM限制列表长度,避免数据膨胀。
四、Redis List 生产避坑与最佳实践
1. 常见坑点规避
- BigKey问题:禁止存储超大列表(超万条元素),LRANGE查询会阻塞Redis,建议拆分列表或用LIMIT分页
- 消息丢失:普通List无ACK机制,消费者宕机消息会丢失,核心业务改用Redis Stream
- 下标越界:LINDEX/LSET操作需先判断列表长度,避免下标无效报错
- 阻塞超时:阻塞出队需合理设置超时时间,避免长时间阻塞占用连接
2. 生产最佳实践
- 队列长度限制:用LTRIM定期裁剪列表,防止内存溢出
- 结合TTL过期:为闲置队列设置TTL,自动清理冷数据(承接上篇TTL知识)
- 禁止全量查询:绝不使用
LRANGE key 0 -1查询全量数据,大数据量分页查询 - 业务选型:轻量级队列用List,核心可靠消息用Stream,去重队列用Set
五、List核心命令速查表
| 操作类型 | 核心命令 | 适用场景 |
|---|---|---|
| 入队操作 | LPUSH、RPUSH | 队列/栈元素添加 |
| 出队操作 | LPOP、RPOP、BLPOP、BRPOP | 元素删除、阻塞消费 |
| 查询操作 | LRANGE、LINDEX、LLEN | 分页展示、长度统计 |
| 高级操作 | LSET、LTRIM、LREM | 列表修改、裁剪、清理 |
核心总结:Redis List是双端有序列表,LPUSH+LPOP实现栈、RPUSH+BRPOP实现阻塞队列,LRANGE实现范围查询,轻量高效适配多种业务;避开BigKey、消息丢失坑点,就能稳定落地生产场景。
结语与下篇预告
List作为Redis最基础的容器型数据结构,掌握其操作与场景落地,是玩转Redis队列、缓存列表的核心。结合上篇TTL机制,还能实现List的自动过期清理,进一步优化内存使用。