列表类型概述
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。列表最多可存储 2^32 - 1 个元素。
列表结构示意图
←
元素1
元素2
元素3
元素4
→
左端(头部) ← 列表 → 右端(尾部)
📝 基本操作命令
列表类型的基础插入和删除操作:
命令 | 描述 | 示例 |
---|---|---|
LPUSH key element [element ...] |
从左端(头部)插入元素 | LPUSH mylist "world" "hello" |
RPUSH key element [element ...] |
从右端(尾部)插入元素 | RPUSH mylist "redis" |
LPOP key |
从左端(头部)弹出元素 | LPOP mylist |
RPOP key |
从右端(尾部)弹出元素 | RPOP mylist |
LLEN key |
获取列表长度 | LLEN mylist |
LINDEX key index |
获取指定索引的元素 | LINDEX mylist 0 |
LSET key index element |
设置指定索引的元素值 | LSET mylist 0 "new_value" |
基本操作示例:
# 创建列表并添加元素 LPUSH tasks "task3" "task2" "task1" # 从左端插入 RPUSH tasks "task4" "task5" # 从右端插入 # 列表内容:["task1", "task2", "task3", "task4", "task5"] # 获取列表信息 LLEN tasks # 返回: 5 LINDEX tasks 0 # 返回: "task1" (第一个元素) LINDEX tasks -1 # 返回: "task5" (最后一个元素) # 弹出元素 LPOP tasks # 返回: "task1" RPOP tasks # 返回: "task5" # 列表内容:["task2", "task3", "task4"] # 修改元素 LSET tasks 0 "updated_task2" # 修改第一个元素 LINDEX tasks 0 # 返回: "updated_task2"
🔍 范围操作命令
获取和操作列表中的元素范围:
命令 | 描述 | 示例 |
---|---|---|
LRANGE key start stop |
获取指定范围的元素 | LRANGE mylist 0 2 |
LTRIM key start stop |
保留指定范围的元素 | LTRIM mylist 0 99 |
LINSERT key BEFORE|AFTER pivot element |
在指定元素前/后插入 | LINSERT mylist BEFORE "world" "beautiful" |
LREM key count element |
删除指定数量的元素 | LREM mylist 2 "hello" |
范围操作示例:
# 创建测试列表 RPUSH numbers 1 2 3 4 5 6 7 8 9 10 # 获取范围元素 LRANGE numbers 0 4 # 返回: ["1", "2", "3", "4", "5"] LRANGE numbers -3 -1 # 返回: ["8", "9", "10"] (最后3个) LRANGE numbers 0 -1 # 返回: 所有元素 # 保留指定范围 LTRIM numbers 0 4 # 只保留前5个元素 LRANGE numbers 0 -1 # 返回: ["1", "2", "3", "4", "5"] # 插入元素 LINSERT numbers AFTER "3" "3.5" # 在"3"后插入"3.5" LRANGE numbers 0 -1 # 返回: ["1", "2", "3", "3.5", "4", "5"] # 删除元素 RPUSH duplicates "a" "b" "a" "c" "a" LREM duplicates 2 "a" # 删除2个"a" LRANGE duplicates 0 -1 # 返回: ["b", "c", "a"]
⏰ 阻塞操作命令
当列表为空时,阻塞等待新元素的命令:
命令 | 描述 | 示例 |
---|---|---|
BLPOP key [key ...] timeout |
阻塞式左端弹出 | BLPOP queue1 queue2 30 |
BRPOP key [key ...] timeout |
阻塞式右端弹出 | BRPOP queue1 30 |
BRPOPLPUSH source destination timeout |
阻塞式弹出并推入另一个列表 | BRPOPLPUSH queue1 queue2 30 |
阻塞操作示例:
# 消费者等待任务(阻塞30秒) BLPOP task_queue 30 # 如果task_queue为空,将阻塞等待30秒 # 如果有新任务被推入,立即返回 # 生产者添加任务(在另一个连接中) LPUSH task_queue "new_task" # 此时阻塞的BLPOP会立即返回 ["task_queue", "new_task"] # 多队列监听 BLPOP high_priority_queue normal_queue low_priority_queue 0 # 按优先级顺序检查队列,0表示永久阻塞 # 原子性转移 BRPOPLPUSH processing_queue completed_queue 30 # 从processing_queue右端弹出,推入completed_queue左端
🔄 列表间操作
在不同列表之间移动元素:
命令 | 描述 | 示例 |
---|---|---|
RPOPLPUSH source destination |
从源列表右端弹出,推入目标列表左端 | RPOPLPUSH list1 list2 |
列表间操作示例:
# 任务处理流程 RPUSH todo "task1" "task2" "task3" RPUSH doing RPUSH done # 开始处理任务 RPOPLPUSH todo doing # 将任务从todo移到doing LRANGE doing 0 -1 # 返回: ["task3"] # 完成任务 RPOPLPUSH doing done # 将任务从doing移到done LRANGE done 0 -1 # 返回: ["task3"] # 查看各阶段任务 LRANGE todo 0 -1 # 返回: ["task1", "task2"] LRANGE doing 0 -1 # 返回: [] LRANGE done 0 -1 # 返回: ["task3"]
实际应用场景
📨 消息队列
使用列表实现简单的消息队列系统:
# 生产者发送消息 LPUSH message_queue "{\"id\": 1, \"type\": \"email\", \"to\": \"user@example.com\"}" LPUSH message_queue "{\"id\": 2, \"type\": \"sms\", \"to\": \"13800138000\"}" # 消费者处理消息 BRPOP message_queue 30 # 阻塞等待消息 # 可靠队列(处理中队列) BRPOPLPUSH message_queue processing_queue 30 # 处理完成后 LREM processing_queue 1 "processed_message" # 失败重试 RPOPLPUSH processing_queue retry_queue
📰 最新动态
存储用户的最新动态或文章列表:
# 发布新动态 LPUSH user:1001:timeline "{\"id\": 101, \"content\": \"今天天气不错\", \"time\": 1609459200}" LPUSH user:1001:timeline "{\"id\": 102, \"content\": \"学习Redis\", \"time\": 1609462800}" # 获取最新10条动态 LRANGE user:1001:timeline 0 9 # 限制动态数量(只保留最新100条) LTRIM user:1001:timeline 0 99 # 获取特定动态 LINDEX user:1001:timeline 0 # 最新动态 LINDEX user:1001:timeline -1 # 最早动态
📊 排行榜
实现简单的排行榜功能:
# 添加分数记录 LPUSH game:leaderboard "player1:1000" LPUSH game:leaderboard "player2:1200" LPUSH game:leaderboard "player3:800" # 获取排行榜 LRANGE game:leaderboard 0 9 # 前10名 # 更新分数(需要先删除旧记录) LREM game:leaderboard 1 "player1:1000" LPUSH game:leaderboard "player1:1500" # 注意:对于复杂排行榜,建议使用Sorted Set
🔄 任务调度
实现任务调度和处理流程:
# 任务提交 LPUSH task:pending "{\"id\": 1, \"type\": \"image_process\", \"file\": \"image1.jpg\"}" LPUSH task:pending "{\"id\": 2, \"type\": \"video_encode\", \"file\": \"video1.mp4\"}" # 工作进程获取任务 BRPOPLPUSH task:pending task:processing 30 # 任务完成 RPOPLPUSH task:processing task:completed # 任务失败 RPOPLPUSH task:processing task:failed # 重试失败任务 RPOPLPUSH task:failed task:pending # 监控队列状态 LLEN task:pending # 待处理任务数 LLEN task:processing # 处理中任务数 LLEN task:completed # 已完成任务数 LLEN task:failed # 失败任务数
性能优化建议
- 避免大列表:单个列表元素数量不宜过多(建议小于10万)
- 使用阻塞操作:在队列场景中使用 BLPOP/BRPOP 避免轮询
- 批量操作:使用 LPUSH/RPUSH 的多元素版本减少网络往返
- 合理使用索引:避免频繁使用 LINDEX 访问中间元素
- 定期清理:使用 LTRIM 限制列表大小
- 选择合适的端:根据业务需求选择从左端还是右端操作
列表 vs 其他数据类型
数据类型选择建议:
- List vs Set:List允许重复元素且有序,Set不允许重复且无序
- List vs Sorted Set:List按插入顺序排序,Sorted Set按分数排序
- List vs Stream:Stream更适合复杂的消息队列场景
- 使用List的场景:消息队列、最新动态、简单排行榜、任务调度