Redis LPUSH 命令详细教程
LPUSH将一个或多个元素插入到列表的表头(左侧)。若 Key 不存在,会先创建空列表再推入;若 Key 存在但不是列表,报错。它从 Redis 1.0.0 起提供,2.4.0 起支持一次推入多个元素,是构建队列、栈和最新内容列表最常用的写入命令之一。
资料合集:https://pan.quark.cn/s/10e98d308913、https://pan.quark.cn/s/f56bc69c5338
一、概览与语法
LPUSH key element [element ...]| 项目 | 说明 |
|---|---|
| 数据类型 | List |
| 支持版本 | Redis 1.0.0 起;2.4.0 起接受多个 element |
| key | 目标列表 Key,不存在时自动创建 |
| element | 一个或多个要推入的元素,按书写顺序逐个推到表头 |
| 返回值 | 推入完成后的列表长度 |
| 时间复杂度 | 每个元素 O(1),一次推 N 个为 O(N) |
| ACL | @write、@list、@fast |
| 命令标记 | write、denyoom、fast |
官方说明:将所有指定值插入到存储于 key 的列表表头。若 key 不存在,先创建空列表再执行推入;若 key 存在但不是列表,返回错误。$TRAE_REF
列表最大长度为 2^32 - 1 个元素(超过 42 亿),实际业务难以触达。
二、基础示例
以下命令在测试实例的 redis-cli 中执行。文中结果是预期说明,未实际连接 Redis 运行。示例沿用官方文档的数据与结果。
DEL tutorial:{lpush}:mylist LPUSH tutorial:{lpush}:mylist "world" LPUSH tutorial:{lpush}:mylist "hello" LRANGE tutorial:{lpush}:mylist 0 -1预期结果:两次 LPUSH 分别返回1、2;LRANGE 返回"hello"、"world"。第二次推入的"hello"排在了表头,说明 LPUSH 是“新元素插队到最前面”。
三、多元素推入顺序
一条 LPUSH 带多个元素时,参数按顺序逐个推到表头,因此最后一个参数最终位于表头:
DEL tutorial:{lpush}:order LPUSH tutorial:{lpush}:order a b c LRANGE tutorial:{lpush}:order 0 -1预期结果:LPUSH 返回3;LRANGE 返回"c"、"b"、"a",与书写顺序正好相反。
这一顺序经常造成误解:想让a排在最前面时,应改用 RPUSH,或把参数倒序书写。版本注意:Redis 2.4 之前的 LPUSH 每次只接受一个元素,多元素写法在老版本会报语法错误。
四、Key 不存在与类型错误
| 场景 | 行为 |
|---|---|
| Key 不存在 | 创建列表并推入,返回元素个数 |
| Key 是其他类型 | 报 WRONGTYPE |
| 只想更新已有列表 | 改用 LPUSHX,Key 不存在时不创建、返回 0 |
DEL tutorial:{lpush}:nx tutorial:{lpush}:str LPUSH tutorial:{lpush}:nx x TYPE tutorial:{lpush}:nx SET tutorial:{lpush}:str text LPUSH tutorial:{lpush}:str x LPUSHX tutorial:{lpush}:nokey x预期结果:第一条 LPUSH 返回1,TYPE 返回list,确认 Key 被自动创建;对 String 类型执行报 WRONGTYPE;LPUSHX 对不存在的 Key 返回0且不创建 Key。
五、与相近命令的区别
| 命令 | 推入位置 | Key 不存在时 | 复杂度 |
|---|---|---|---|
| LPUSH | 表头(左侧) | 创建列表后推入 | O(1)/元素 |
| RPUSH | 表尾(右侧) | 创建列表后推入 | O(1)/元素 |
| LPUSHX | 表头(左侧) | 不创建,返回 0 | O(1)/元素 |
| RPUSHX | 表尾(右侧) | 不创建,返回 0 | O(1)/元素 |
| LINSERT | 指定 pivot 前后 | 不创建,返回 0 | O(N) |
| LMOVE | 从源列表弹出并推入目标列表 | 目标列表按需创建 | O(1) |
LPUSH 只负责“推入”,不返回被弹出的元素;需要在推入的同时裁剪列表长度时,配合 LTRIM 使用。
六、队列与栈模式
LPUSH 与不同弹出命令组合,可构成两种经典结构:
| 组合 | 语义 |
|---|---|
| LPUSH 入队 + RPOP/BRPOP 出队 | 先进先出(FIFO)队列 |
| LPUSH 入队 + LPOP 出队 | 后进先出(LIFO)栈 |
| RPUSH 入队 + BLPOP 出队 | FIFO 队列,消费者阻塞等待 |
DEL tutorial:{lpush}:stack LPUSH tutorial:{lpush}:stack a b c LPOP tutorial:{lpush}:stack RPOP tutorial:{lpush}:stack预期结果:LPUSH 后列表为c,b,a;LPOP 弹出"c"(最后推入的最先出,栈语义);RPOP 弹出"a"(最先推入的最先出,队列语义)。
七、边界情况与错误处理
| 场景 | 行为 |
|---|---|
| Key 不存在 | 自动创建并推入 |
| Key 类型不是 List | 报 WRONGTYPE |
| 未提供任何 element | 参数数量不足,报语法错误 |
| element 为空字符串 | 允许,正常推入 |
| 返回值 | 恒为推入后的列表长度,非布尔值 |
SET tutorial:{lpush}:str text LPUSH tutorial:{lpush}:str x LPUSH tutorial:{lpush}:err预期结果:第一条报 WRONGTYPE;第二条缺少元素参数,报ERR wrong number of arguments for 'lpush' command。
八、客户端示例
前提为已安装 redis-py 并准备好本地测试实例。redis-py 的lpush(name, *values)返回推入后的列表长度。
importredis r=redis.Redis(host="localhost",port=6379,decode_responses=True)key="tutorial:{lpush}:py"try:r.delete(key)print(r.lpush(key,"a","b","c"))# 3print(r.lrange(key,0,-1))# ['c', 'b', 'a']print(r.lpush(key,""))# 4,允许空字符串元素print(r.llen(key))# 4finally:r.delete(key)r.close()Java(Jedis)示例:
try(Jedisjedis=newJedis("localhost",6379)){Stringkey="tutorial:{lpush}:java";jedis.del(key);System.out.println(jedis.lpush(key,"a","b","c"));// 3System.out.println(jedis.lrange(key,0,-1));// [c, b, a]System.out.println(jedis.lpushx("no-such-key","x"));// 0,Key 不存在时不创建jedis.del(key);}九、原子性、事务与 Pipeline
原子性:LPUSH 是单命令原子操作。多个生产者并发向同一个列表 LPUSH 时不会互相覆盖,元素按到达顺序依次排列,因此天然适合多生产者写入同一队列。
Pipeline:高频写入场景可将多条 LPUSH 打包进管道,减少网络往返;单条命令的原子性不受影响。
事务:LPUSH 在 MULTI/EXEC 中正常排队执行,返回推入后的长度;与 BLPOP 等阻塞命令不同,它没有事务内特殊行为。
性能:每个元素 O(1),只操作表头,与列表长度无关;列表底层在元素少时使用 listpack、多时使用快速链表,两端操作都很快。
十、集群、连接与并发注意事项
集群模式:LPUSH 只涉及单个 Key,没有跨槽限制;但同一队列的所有生产者与消费者都访问同一 Key,注意热点分片问题。
防无限增长:配合 LTRIM 限制长度,例如LPUSH feed item后执行LTRIM feed 0 999,只保留最新 1000 条,避免长列表占用内存并拖慢遍历类命令。
连接占用:LPUSH 本身不阻塞;阻塞的是消费端的 BLPOP/BRPOP,无限等待会独占连接,注意连接池规划。
十一、典型业务场景
最新内容列表:朋友圈动态、公告、最新订单等“只看最新 N 条”的场景,LPUSH 写入 + LTRIM 裁剪,读取用 LRANGE 0 N-1。
任务队列生产端:LPUSH 投递任务,消费端用 BRPOP 阻塞领取,构成 FIFO 队列;需要可靠投递时消费端改用 BLMOVE。
操作撤销栈:用户每步操作 LPUSH 记录,回退时 LPOP 取出,天然后进先出。
浏览历史:LPUSH user:history item记录访问轨迹,配合 LREM 去重、LTRIM 限长。
十二、练习、排错与总结
练习:新建tutorial:{lpush}:ex1与tutorial:{lpush}:ex2;对 ex1 执行LPUSH ex1 a b c,确认返回3且 LRANGE 得到c,b,a;对不存在的 ex2 执行LPUSHX ex2 x,确认返回0且 EXISTS 为0;用 SET 把 ex1 改成 String 后再 LPUSH,确认报 WRONGTYPE,最后 DEL 该 Key。
排错要点:LRANGE 顺序与预期相反时检查多元素参数的书写顺序,最后一个参数在表头;报 WRONGTYPE 时用 TYPE 检查 Key 是否被 String 等类型占用;返回 0 而不是报错时,确认是否误用了 LPUSHX;列表异常变长时检查是否漏了 LTRIM。清理使用DEL tutorial:{lpush}:mylist tutorial:{lpush}:order tutorial:{lpush}:nx tutorial:{lpush}:str tutorial:{lpush}:stack tutorial:{lpush}:py tutorial:{lpush}:java tutorial:{lpush}:ex1 tutorial:{lpush}:ex2。速记:1.0 起支持、2.4 起可一次推多个、推到表头、返回推入后的长度、Key 不存在自动创建、最后一个参数排在最前、LPUSH+RPOP 是队列、LPUSH+LPOP 是栈、只想更新已有列表用 LPUSHX、限长配合 LTRIM。