Redis Pipeline 和 MGET,如果报错了,他们的异常机制是什么样的?

文章首发到公众号:月伴飞鱼,每天分享程序员职场经验!

文章内容收录到个人网站,方便阅读:hardyfish.top/

Redis pipeline 和 MGET 的异常机制

当 Redis pipeline 和 MGET 在执行过程中遇到错误时,它们的错误处理机制有所不同,具体如下:

1. MGET 的异常机制

情况 1:某个 Key 不存在

  • MGET 对于不存在的 key,不会报错,而是返回 nil(Python 中是 None)。

  • 示例:

    go 复制代码
    redis> MGET key1 key2 key3
    1) "value1"
    2) nil
    3) "value3"
    • key2 不存在,但 MGET 不会抛出异常 ,只是返回 nil。

情况 2:Redis 服务器崩溃

  • 如果 Redis 服务器 不可用(down) ,MGET 调用会失败,返回 连接异常。

  • Python 示例:

    python 复制代码
    import redis
    ​
    r = redis.StrictRedis(host="127.0.0.1", port=6379, decode_responses=True)
    ​
    try:
        result = r.mget(["key1", "key2"])
        print(result)
    except redis.exceptions.ConnectionError as e:
        print(f"Redis 连接失败: {e}")
    • 当 Redis 宕机 时,会抛出 redis.exceptions.ConnectionError。

情况 3:跨分片查询(Redis Cluster 模式)

  • MGET 不能跨分片 ,如果 keys 在不同分片,会报 CROSSSLOT 错误:

    vbnet 复制代码
    (error) CROSSSLOT Keys in request don't hash to the same slot
  • 解决方案:

    • 确保 keys 在同一槽位 ,使用 哈希标签 {}:

      sql 复制代码
      MGET {user}:1 {user}:2

2. pipeline 的异常机制

情况 1:某个命令失败

  • pipeline 不会影响整个批次,即使其中某个命令失败,Redis 仍然会继续执行其他命令。

  • 示例:

    python 复制代码
    import redis
    ​
    r = redis.StrictRedis(host="127.0.0.1", port=6379, decode_responses=True)
    ​
    pipe = r.pipeline()
    pipe.set("key1", "value1")
    pipe.get("non_existing_key")  # 不存在的 key,不会报错,只返回 None
    pipe.lpush("key1", "value2")  # 错误:尝试对字符串执行列表操作
    pipe.get("key1")
    ​
    try:
        results = pipe.execute()
        print(results)
    except redis.exceptions.RedisError as e:
        print(f"Redis 命令失败: {e}")
    • 如果 LPUSH key1 value2 失败,它 不会影响 get key1 的执行,Redis 仍然返回部分成功的结果:

      css 复制代码
      ['OK', None, ResponseError('WRONGTYPE Operation against a key holding the wrong kind of value'), 'value1']

情况 2:Redis 服务器崩溃

  • 如果 Redis 服务器宕机或连接断开:

    python 复制代码
    try:
        pipe = r.pipeline()
        pipe.set("key1", "value1")
        pipe.execute()
    except redis.exceptions.ConnectionError as e:
        print(f"Redis 连接失败: {e}")
    • 所有 pipeline 命令都会失败 ,返回 redis.exceptions.ConnectionError。

情况 3:跨分片查询(Redis Cluster 模式)

  • pipeline 可以跨分片执行 ,但 Redis 会自动拆分请求 并分别发送到不同分片,不会报 CROSSSLOT 错误。

  • 但如果 某个分片发生错误,会导致部分请求失败:

    python 复制代码
    import rediscluster
    ​
    startup_nodes = [{"host": "127.0.0.1", "port": 6379}]
    rc = rediscluster.RedisCluster(startup_nodes=startup_nodes, decode_responses=True)
    ​
    pipe = rc.pipeline()
    pipe.get("user:1")  # 可能在 shard1
    pipe.get("order:123")  # 可能在 shard2
    ​
    try:
        results = pipe.execute()
        print(results)
    except redis.exceptions.RedisClusterException as e:
        print(f"Redis Cluster 失败: {e}")
    • 部分 key 可能成功,部分失败,需要在应用层检查返回值。

3. pipeline vs MGET 异常处理对比

异常情况 MGET pipeline
Key 不存在 返回 nil 返回 None
单个命令错误 MGET 只有 GET,基本不会报错 只影响该条命令,不影响其他命令
Redis 宕机 连接异常 (ConnectionError) 整个 pipeline 失败 (ConnectionError)
跨分片查询 CROSSSLOT 错误 支持跨分片,但可能部分失败
部分命令失败 N/A 失败的命令返回 ResponseError,其余命令不受影响

4. 结论

  • 如果 key 可能不存在:

    • MGET 只会返回 nil,不会报错。
    • pipeline 返回 None,但仍然继续执行后续命令。
  • 如果 Redis 宕机:

    • MGET 和 pipeline 都会失败 ,但 pipeline 影响范围更大。
  • 如果 Redis Cluster 跨分片:

    • MGET 不支持 ,报 CROSSSLOT 错误。
    • pipeline 支持,但部分 key 可能失败。
  • 如果某个命令失败:

    • pipeline 不会影响其他命令 ,但需要在代码中手动处理 ResponseError。

总结

  • 批量读取推荐 MGET,如果 key 都在一个分片。
  • 批量操作(读写混合)用 pipeline,但要注意部分失败情况。
  • 分布式 Redis(Cluster 模式)推荐 pipeline,但要处理可能的部分失败情况。
相关推荐
爱勇宝9 分钟前
《道德经》第 13 章:别让评价系统控制你的心
前端·后端·产品
掘金者阿豪14 分钟前
集中式与分布式数据库怎么选?从架构原理到电科金仓的实践思考
前端·后端
.痞老板.36 分钟前
java ee--计算机是如何工作的
java·开发语言·java-ee
张彦峰ZYF1 小时前
升级了不等于变好了:AI回归测试的固定评测集、版本对比、质量阈值与CI门禁
人工智能·后端·模型或提示词升级·语言模型没有编译器与确定性输出·总体、切片与回退清单·红线、护栏与目标·ci门禁把判定写进合并路径
青梅味猪大肠1 小时前
【操作系统-60】临近适应算法
java·linux·开发语言·嵌入式硬件·算法·操作系统
CoderYanger1 小时前
Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)
java·数据库·spring·面试·职场和发展·java-ee·mybatis
程序员沉梦听雨1 小时前
【搜索引擎】Kibana使用指南
java·后端·学习笔记
Cosolar1 小时前
极简智库(MiniDocs):docsify、VitePress、Notion 等知识库搭建服务的完美替代
前端·后端·架构
Goboy2 小时前
夯爆了,我被一个一句话接入的免费可观测平台策反了,那一刻我决定放弃用了3年的Prometheus
后端·docker·kubernetes
奶油话梅糖2 小时前
打开项目 0.9 秒、内存只有 IDEA 的 1/12:OpenIDEA 用 Rust 把 IntelliJ IDEA 重造了一遍
java·rust·github·intellij-idea