*Redis 中RESP2和RESP3的区别

在 Redis 中,RESP2(旧版协议)和 RESP3(从 Redis 6 开始引入的新版协议)在命令返回值上的最大区别在于数据类型的语义化

在 RESP2 时代,协议类型非常贫乏(只有字符串、整数、错误和数组),客户端必须根据“常识”或硬编码的规则去解析数据(例如把 HGETALL 返回的一维数组按键值对两两配对)。而 RESP3 引入了丰富的原生数据类型(如 Map、Set、Boolean、Double 等),使得服务器可以直接返回具有明确语义的数据结构。

以下是两代协议在具体命令返回值上的核心差异汇总:

*1. Hash 命令(键值对解析)

在 RESP2 中,Redis 没有字典(Map)类型,只能用“扁平化数组”来凑。RESP3 原生支持了 Map 类型(%),彻底解决了客户端需要手动配对键值的问题。

  • 受影响命令HGETALLCONFIG GETHELLO 以及某些 Stream 相关的命令(如 XPENDING 等)。
  • RESP2 返回:扁平数组 ["field1", "value1", "field2", "value2"]
  • RESP3 返回:原生 Map {"field1": "value1", "field2": "value2"}

*2. Set(集合)命令

RESP2 没有集合概念,所有集合命令都返回普通数组,客户端无法区分这是不是一个去重的集合。RESP3 引入了 Set 类型(~)。

  • 受影响命令SMEMBERSSINTERSUNIONSDIFF 等。
  • RESP2 返回:普通数组 ["member1", "member2"]
  • RESP3 返回:原生 Set 结构 {"member1", "member2"}(对客户端库而言,直接反序列化为 Set/HashSet)。

*3. 布尔值 (Boolean)

RESP2 没有布尔类型,通常用整数 1 代表 true0 代表 false。RESP3 引入了原生布尔类型(#t#f)。

  • 受影响命令EXISTSSISMEMBERHEXISTSSETNX 等。
  • RESP2 返回:整数 :1:0
  • RESP3 返回:布尔值 #t (True) 或 #f (False)

*4. 浮点数 (Double)

在 RESP2 中,浮点数计算的结果被当作字符串返回,客户端需要自己执行 StringToDouble 转换,这不仅浪费性能还容易损失精度。RESP3 引入了原生双精度浮点类型(,)。

  • 受影响命令ZSCOREINCRBYFLOATGEODIST 等。
  • RESP2 返回:字符串 "$4\r\n3.14\r\n"
  • RESP3 返回:双精度浮点数 ,3.14\r\n

*5. 空值 (Null)

RESP2 对空值的表达非常别扭,分为“Null 字符串”($-1)和“Null 数组”(*-1)。RESP3 统一并简化了它,引入了真正的 Null 类型(_)。

  • 受影响命令GET(键不存在时)、BLPOP(超时时)、LPOP(列表为空时)等。
  • RESP2 返回:Null Bulk String 或 Null Array
  • RESP3 返回:原生 Null _\r\n

*6. 长文本与诊断信息

对于需要直接打印给人类看的长文本,RESP3 引入了 Verbatim String(逐字字符串 =,它告诉客户端:“不要做任何排版和转换,请直接原样输出它”。

  • 受影响命令INFOMEMORY DOCTORCLIENT LIST 等。
  • RESP2 返回:普通的块字符串 (Bulk String)
  • RESP3 返回:带有 txt: 前缀的 Verbatim String。

*7. Pub/Sub 与异步推送

这是导致 Redis 必须升级 RESP3 的根本原因之一。在 RESP2 中,如果你使用了 SUBSCRIBE(订阅)命令,Redis 推送的消息本质上就是普通的数组,这导致客户端无法在同一个连接上混用 Pub/Sub 和普通命令

  • 受影响场景:发布订阅 (SUBSCRIBE/PSUBSCRIBE),以及 Redis 6 引入的 客户端缓存机制 (Client-side Caching)
  • RESP2 返回:普通数组,霸占整个连接通道。
  • RESP3 返回:全新的 Push 类型 (>)。它是一种“带外(Out-of-band)”数据,客户端库在解析时,可以将 Push 消息抛给后台事件循环,而不干扰主连接正常的 Request/Response 流程。

*总结与验证

如果你想直观地感受这些区别,可以通过 telnetnc 直接连上 Redis Server,然后使用 HELLO 3 命令。

  • 默认情况下(或发送 HELLO 2),连接处于 RESP2 模式。
  • 发送 HELLO 3 后,当前连接就会无缝切换到 RESP3 协议,你再执行上述提到的命令,就能在抓包层面看到数据前缀(如 %#, 等)发生了本质变化。