Redis命令:RPUSHX

Redis RPUSHX 命令详细教程

RPUSHX 将一个或多个元素追加到列表的表尾(右侧),与 RPUSH 的唯一区别是:只有当 Key 已存在且持有列表时才执行推入 ,Key 不存在时不创建、不报错,静默返回 0。它从 Redis 2.2.0 起提供,4.0.0 起支持一次推入多个元素,适合"只更新、不新建"的保护性写入场景。

资料合集:https://pan.quark.cn/s/10e98d308913、https://pan.quark.cn/s/f56bc69c5338

一、概览与语法

redis 复制代码
RPUSHX key element [element ...]
项目 说明
数据类型 List
支持版本 Redis 2.2.0 起;4.0.0 起接受多个 element
key 目标列表 Key,必须已存在
element 一个或多个要追加的元素,按书写顺序依次追加到表尾
返回值 推入后的列表长度;Key 不存在时返回 0
时间复杂度 每个元素 O(1),一次推 N 个为 O(N)
ACL @write、@list、@fast
命令标记 write、fast、denyoom

官方说明:当 key 已存在且持有列表时,RPUSHX 将所有指定值插入到存储于 key 的列表尾部;与 RPUSH 相反,当 key 尚不存在时不执行任何操作。$TRAE_REF

二、基础示例

以下命令在测试实例的 redis-cli 中执行。文中结果是预期说明,未实际连接 Redis 运行。示例沿用官方文档的数据与结果。

redis 复制代码
DEL tutorial:{rpushx}:mylist tutorial:{rpushx}:myotherlist
RPUSH tutorial:{rpushx}:mylist "World"
RPUSHX tutorial:{rpushx}:mylist "Hello"
RPUSHX tutorial:{rpushx}:myotherlist "Hello"
LRANGE tutorial:{rpushx}:mylist 0 -1
EXISTS tutorial:{rpushx}:myotherlist

预期结果:RPUSH 返回 1;对已存在的 mylist 追加返回 2;对不存在的 myotherlist 追加返回 0;LRANGE 返回 "World"、"Hello"(参数顺序即列表顺序);EXISTS 返回 0,确认 myotherlist 未被创建。

三、与 RPUSH 的核心差异

对比项 RPUSH RPUSHX
Key 存在且为列表 追加并返回新长度 追加并返回新长度
Key 不存在 先创建空列表再追加 不创建,返回 0
副作用 可能凭空产生新 Key 无,绝不新建 Key
支持多元素 2.4.0 起 4.0.0 起

这个差异决定了两者的适用面:RPUSH 适合初始化与常规写入;RPUSHX 把"判断存在"和"追加"合并成一次原子操作,避免"先 EXISTS 检查再 RPUSH"这种两步流程在并发下产生的竞态。

四、多元素推入顺序

与 RPUSH 一致,多个元素按参数顺序依次追加到表尾,参数的书写顺序即最终列表顺序:

redis 复制代码
DEL tutorial:{rpushx}:order
RPUSH tutorial:{rpushx}:order seed
RPUSHX tutorial:{rpushx}:order a b c
LRANGE tutorial:{rpushx}:order 0 -1

预期结果:RPUSHX 返回 4;LRANGE 返回 "seed"、"a"、"b"、"c"。版本注意:Redis 4.0 之前的 RPUSHX 每次只接受一个元素。

五、Key 不存在与类型错误

RPUSHX 返回 0 只有一种正常情形:Key 当前不存在(含刚被弹出最后一个元素而删除的情况)。列表类型不会以"空列表"形式存在,元素弹完 Key 即被删除。

场景 行为
Key 不存在 不创建,返回 0
Key 是其他类型 报 WRONGTYPE
Key 已存在且为列表 追加,返回新长度
Key 设置过 TTL 追加不清除过期时间,到期仍会被删除
redis 复制代码
SET tutorial:{rpushx}:str text
RPUSHX tutorial:{rpushx}:str x

预期结果:对 String 类型执行报 WRONGTYPE,类型检查先于任何写入。

六、与相近命令的区别

命令 推入位置 Key 不存在时 支持多元素
RPUSHX 表尾(右侧) 不创建,返回 0 4.0.0 起
RPUSH 表尾(右侧) 创建列表后推入 2.4.0 起
LPUSHX 表头(左侧) 不创建,返回 0 4.0.0 起
LPUSH 表头(左侧) 创建列表后推入 2.4.0 起
LINSERT 指定 pivot 前后 不创建,返回 0 不支持

四个命令的分工很清晰:普通命令负责"有则推、无则建",X 命令负责"有则推、无则放弃"。RPUSHX 与 LPUSHX 的区别仅在推入端:前者追加到表尾,后者插到表头。

七、边界情况与错误处理

场景 行为
未提供任何 element 参数数量不足,报语法错误
element 为空字符串 允许,正常推入
Key 不存在 返回 0,静默成功
Key 类型不是 List 报 WRONGTYPE
返回值语义 0 表示未推入(Key 不存在),正数表示推入后的长度
redis 复制代码
RPUSHX tutorial:{rpushx}:err

预期结果:缺少元素参数,报 ERR wrong number of arguments for 'rpushx' command。

业务代码需要注意:RPUSHX 返回 0 不是错误,但通常意味着"列表尚未初始化",调用方应据此决定是否先执行初始化,而不是把它当成失败重试。

八、客户端示例

前提为已安装 redis-py 并准备好本地测试实例。redis-py 的 rpushx(name, *values) 返回推入后的长度,Key 不存在时返回 0。

python 复制代码
import redis

r = redis.Redis(host="localhost", port=6379, decode_responses=True)
key = "tutorial:{rpushx}:py"
try:
    r.delete(key)
    print(r.rpushx(key, "a", "b", "c"))    # 0,Key 不存在不创建
    r.rpush(key, "seed")
    print(r.rpushx(key, "a", "b", "c"))    # 4
    print(r.lrange(key, 0, -1))            # ['seed', 'a', 'b', 'c']
finally:
    r.delete(key)
    r.close()

Java(Jedis)示例,rpushx 同样支持可变参数:

java 复制代码
try (Jedis jedis = new Jedis("localhost", 6379)) {
    String key = "tutorial:{rpushx}:java";
    jedis.del(key);

    System.out.println(jedis.rpushx(key, "a"));
    // 0,Key 不存在不创建
    jedis.rpush(key, "seed");
    System.out.println(jedis.rpushx(key, "a", "b", "c"));
    // 4
    System.out.println(jedis.lrange(key, 0, -1));
    // [seed, a, b, c]
    jedis.del(key);
}

九、原子性与使用注意事项

检查与写入合一 :EXISTS key 加 RPUSH key x 是两步流程,中间可能被其他客户端删除 Key 或改变类型;RPUSHX 把"必须已存在"作为前置条件在服务端一次性校验,是天然原子的。

TTL 不受影响:对已设置过期时间的 Key 执行 RPUSHX 不会清除 TTL。若业务期望"写入后重新计时",需要显式重设 EXPIRE。

Pipeline 与事务:RPUSHX 可正常用于管道与 MULTI/EXEC,返回值语义不变;批量追加用管道减少网络往返。

性能:每个元素 O(1),只操作表尾,与列表长度无关。

十、典型业务场景

保护性追加:时序日志、审计流水、事件流等由专门的初始化逻辑(写入元数据、设置 TTL)创建 Key 后,后续写入全部走 RPUSHX,防止下游异常调用凭空造出没有 TTL、没有元数据的孤儿 Key。

会话期流水:用户会话存在才继续记录操作流水,会话过期后自然停止追加,无需额外判断。

并发初始化保护:多个服务实例同时写同一个列表时,用 RPUSHX 保证"谁负责创建、谁才能写入"的语义清晰。

追加已有集合的明细:主记录存在才追加其明细项,避免产生孤立明细。

十一、练习、排错与总结

练习:新建 tutorial:{rpushx}:ex1 与 tutorial:{rpushx}:ex2;对不存在的 ex1 执行 RPUSHX ex1 a,确认返回 0 且 EXISTS 为 0;执行 RPUSH ex1 seed 后执行 RPUSHX ex1 b c,确认返回 3 且 LRANGE 得到 seed,b,c;用 SET 把 ex1 改成 String 后再 RPUSHX,确认报 WRONGTYPE;最后对 ex2 重复验证 Key 不存在时的静默行为。

排错要点:RPUSHX 返回 0 时先怀疑 Key 未初始化,用 EXISTS、TYPE 确认;本想初始化列表时不要误用 RPUSHX,改用 RPUSH;报 WRONGTYPE 时检查 Key 是否被 String 等类型占用;老版本(4.0 前)报语法错误时检查是否使用了多元素写法;追加顺序与预期不符时确认元素是否被追加到表尾(RPUSHX 参数顺序即列表顺序)。清理使用 DEL tutorial:{rpushx}:mylist tutorial:{rpushx}:myotherlist tutorial:{rpushx}:order tutorial:{rpushx}:str tutorial:{rpushx}:py tutorial:{rpushx}:java tutorial:{rpushx}:ex1 tutorial:{rpushx}:ex2。速记:2.2 起支持、4.0 起可推多个、只在 Key 已存在时追加到表尾、Key 不存在返回 0 且不创建、返回值为推入后的长度、不清除已有 TTL、与 RPUSH 的区别就在"是否创建"、X 系列命令都是"有则推无则弃"。

相关推荐
看浪的路人2 小时前
第9讲:记忆系统的性能优化与基准测试——缓存策略、连接池、批量操作与压测方法论
缓存·性能优化
星夜孤帆3 小时前
Redis缓存击穿与分布式锁实战:专栏目录、源码与实验说明
redis·分布式·缓存
SHENGWEI胜为4 小时前
NVMe SSD写入速度突然下降?从SLC缓存耗尽到温度降速的排查方法
网络·缓存
clz13145214 小时前
ruoyi-cloud功能开发demo实战:三级联动 Redis Hash 缓存查看器
redis·缓存·哈希算法
杨运交5 小时前
080-缓存模块-Spring Cache缓存键前缀设计与租户隔离实践
java·spring·缓存
Pniubi1 天前
力扣146.LRU缓存机制
算法·leetcode·缓存
欣栀♡1 天前
Spring 循环依赖不止三级缓存,Boot 2.6 起这个开关默认已经关了
java·spring·缓存
xiaoqiMikko1 天前
Redis 实战(二):宕机会丢多少数据 —— kill -9 与真断电下 RDB / AOF 逐个实测(6.2.4)
redis·后端
夕除1 天前
redis--ziplist
redis