Redis命令-List命令

一、前言:List 不只是"列表",更是轻量级队列

在 Redis 中,List(列表) 是一个基于双向链表 实现的数据结构,支持从头部或尾部高效插入/删除元素。

它不仅是简单的数据容器,更是实现:

  • ✅ 轻量级消息队列
  • ✅ 最新动态/评论流
  • ✅ 任务分发系统
  • ✅ 秒杀库存缓冲池

的利器!

本文将带你:

✅ 掌握 List 的核心命令(含阻塞操作)

✅ 理解其底层实现(quicklist)

✅ 结合真实业务场景

✅ 避开性能陷阱


二、List 类型基本特性

  • 有序:元素按插入顺序排列
  • 允许重复:同一个值可多次出现
  • 支持双向操作:左(Left/Head)和右(Right/Tail)
  • 底层编码quicklist(Redis 3.2+),由 ziplist 组成的双向链表,兼顾内存与性能
  • 最大长度:2^32 - 1 个元素(约 42 亿)

三、核心命令详解(附实战示例)

1. LPUSH / RPUSH ------ 从左侧/右侧插入

bash 复制代码
# 从左侧推入(新元素在头部)
LPUSH news:list "新闻A"
LPUSH news:list "新闻B"  # 此时列表:["新闻B", "新闻A"]

# 从右侧推入(新元素在尾部)
RPUSH task:queue "task1"
RPUSH task:queue "task2" # 列表:["task1", "task2"]

💡 口诀

  • LPUSHL eft Push → (后进先出)
  • RPUSH + LPOP队列(先进先出)

2. LPOP / RPOP ------ 从左侧/右侧弹出

bash 复制代码
# 弹出最新新闻(LIFO)
LPOP news:list
# 返回 "新闻B"

# 消费任务(FIFO)
LPOP task:queue
# 返回 "task1"

⚠️ 如果 List 为空,返回 (nil)


3. BLPOP / BRPOP ------ 阻塞式弹出(关键!)

当 List 为空时,阻塞等待直到有新元素或超时。

bash 复制代码
# 阻塞等待 task:queue,最多等 10 秒
BLPOP task:queue 10

# 同时监听多个队列(优先级队列)
BLPOP high_priority_queue low_priority_queue 0  # 0 表示永久等待

典型用途

  • 消费者进程空闲时自动挂起,节省 CPU
  • 实现可靠的生产者-消费者模型

4. LRANGE key start stop ------ 获取范围元素

bash 复制代码
# 获取最新 5 条新闻(从头开始)
LRANGE news:list 0 4

# 获取全部元素(慎用!)
LRANGE mylist 0 -1

🔍 索引说明:

  • 0 表示第一个元素
  • -1 表示最后一个
  • -2 表示倒数第二个
    ⚠️ 注意LRANGE 时间复杂度 O(N),大数据量会慢!

5. LLEN key ------ 获取列表长度

bash 复制代码
LLEN task:queue
# 返回 3

✅ O(1) 操作,因为 Redis 内部维护了长度计数器。


6. LINDEX / LSET ------ 按索引访问(慎用!)

bash 复制代码
# 获取第 2 个元素(从 0 开始)
LINDEX mylist 1

# 设置第 3 个元素的值
LSET mylist 2 "new_value"

⚠️ 严重警告

  • LINDEXLSET 时间复杂度为 O(N)
  • 在长列表中使用会导致 Redis 卡顿
    替代方案 :如需随机访问,考虑用 ZSet(score = index)

7. LTRIM key start stop ------ 裁剪列表(保留指定范围)

bash 复制代码
# 只保留最新的 100 条消息
LPUSH message:history "msg1"
...
LTRIM message:history 0 99

经典用法 :实现固定长度的最新记录缓存


四、List 的典型应用场景

场景 1:最新动态/朋友圈 Feed 流

bash 复制代码
# 用户发布动态
LPUSH feed:user:1001 "今天去爬山了!"

# 获取最新 10 条
LRANGE feed:user:1001 0 9

✅ 优势:天然按时间倒序,插入快,读取快


场景 2:轻量级消息队列

bash 复制代码
# 生产者:推送任务
RPUSH job:queue "send_email:user123"

# 消费者:阻塞消费
BLPOP job:queue 0

⚠️ 注意:

  • 不支持 ACK 机制(消息可能丢失)
  • 高可靠场景请用 RabbitMQ/Kafka
    ✅ 适用:内部通知、日志收集、异步解耦等容忍少量丢失的场景

场景 3:秒杀库存预扣减

bash 复制代码
# 初始化:将库存 ID 入队(如 100 个商品)
for i in {1..100}; do
  RPUSH seckill:stock:8888 "item_$i"
done

# 秒杀时:原子出队
item_id = LPOP seckill:stock:8888
if item_id:
    # 创建订单
else:
    # 库存不足

🔒 优势:利用 List 的原子性,避免超卖!


五、List vs 其他数据结构对比

需求 推荐类型
先进先出队列 List(RPUSH + LPOP)
优先级队列 ZSet(score = 优先级)
去重队列 Set + List 组合Stream
固定长度最新列表 List + LTRIM
高可靠消息队列 Redis Stream(5.0+)

📌 List 的定位 :简单、高效、轻量,但不保证消息可靠性


六、常见误区与最佳实践

❌ 误区 1:用 LINDEX 随机访问大列表

后果 :O(N) 操作导致 Redis 主线程阻塞
建议 :改用 ZSet 模拟数组(ZADD list 0 "val0"ZADD list 1 "val1"

❌ 误区 2:List 存储超大对象(如 1MB 的 JSON)

问题 :单次 LRANGE 可能返回几十 MB 数据,拖垮网络
建议:List 只存 ID,详情查数据库或 Hash

✅ 最佳实践:

  • 限制 List 长度 :配合 LTRIM 保持固定大小
  • 消费者用 BLPOP:避免轮询,降低 CPU
  • Key 命名规范queue:order_createfeed:user:1001
  • 避免 LRANGE 0 -1:改用分页(如每次取 20 条)

七、底层实现:为什么 Redis List 这么快?

Redis 3.2 之后,List 底层采用 quicklist

  • 本质是 ziplist 的双向链表
  • 每个 ziplist 节点存储多个元素(默认 2KB)
  • 优点
    • 小列表:连续内存,缓存友好
    • 大列表:链表结构,插入/删除 O(1)

💡 这种设计平衡了内存碎片与访问效率。


八、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!

相关推荐
zqmattack2 小时前
SQL sever根据身份证判断性别函数
java·数据库·sql
hanqunfeng2 小时前
(七)Redis 命令及数据类型 -- Hash
数据库·redis·哈希算法
惊讶的猫2 小时前
redis总结
redis
符哥20082 小时前
基于mysql如何设置一个商城的数据库结构
数据库·mysql·oracle
chuxinweihui2 小时前
MySQL库数据类型
数据库·mysql
工业HMI实战笔记2 小时前
HMI权限分级设计:兼顾安全与操作效率的平衡术
运维·数据库·安全·ui·自动化·人机交互·交互
为自己_带盐2 小时前
架构演进:从数据库“裸奔”到多级防护
数据库·架构
深蓝电商API2 小时前
Scrapy与MongoDB管道集成:异步存储方案
数据库·scrapy·mongodb
松涛和鸣3 小时前
DAY56 ARM Cortex-A Bare Metal
linux·服务器·c语言·开发语言·arm开发·数据库