上一篇我们详细拆解了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阻塞右侧弹出,超时返回nullBRPOP 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的自动过期清理,进一步优化内存使用。

发表回复