【大白话说Java面试题 第184题】【07_Redis篇】第20题:Redis 底层使用的什么协议?
PDF大白话说Java面试题 — 07_Redis篇第20题Redis 底层使用的什么协议回答核心考点 Redis 底层通信协议 RESPRedis Serialization Protocol是面试中看似简单实则深藏玄机的考点。大厂面试官不会只问RESP 有哪些数据类型而是深入考察RESP 的完整设计哲学为什么不用 JSON/XML、RESP2 与 RESP3 的演进差异Redis 6.0 引入的 Push 类型、Big Number、Verbatim String 等、协议解析的零拷贝优化、Pipeline 和 Pub/Sub 在协议层面的实现差异以及自定义 Redis 客户端时协议解析的性能陷阱。面试官真正想判断的是你是否理解简单协议设计背后的工程权衡以及能否在协议层面优化 Redis 通信性能。1. RESP 协议的设计哲学与版本演进1.1 为什么 Redis 选择自定义协议而非 JSON/XMLRedis 作者 antirez 在设计 RESP 时遵循三个核心原则设计原则RESP 实现JSON/XML 对比解析效率前缀标识符 CRLF 分隔状态机解析 O(1)JSON 需递归解析XML 需 DOM/SAX内存友好流式解析无需预读完整数据JSON 通常需完整加载到内存类型丰富原生支持二进制安全字符串、整数、数组JSON 只有字符串/数字/对象/数组实现简单任何语言 100 行代码即可实现客户端JSON 库通常数千行可读性文本协议telnet 可直接调试同样文本可读关键决策RESP 是二进制安全的——$6 foobar中的foobar可以是任意二进制数据包括 而 JSON 的字符串必须转义控制字符。1.2 RESP2Redis 2.x~5.x——五种基础类型RESP2 定义了五种基础数据类型每种以特定前缀字符标识类型前缀名称用途示例Simple String简单状态回复OK| |-| Error | 错误信息 |-ERR wrong number of arguments| |:| Integer | 整数回复 |:1000| |$| Bulk String | 二进制安全字符串 |6 f o o b a r ‘ 、 ‘ 6 foobar 、 6foobar‘、‘-1nil | |*| Array | 数组/命令参数 |*2$3foo$3bar |协议格式规则每行以 CRLF结尾批量字符串$先传长度十进制再传内容长度-1表示 nil数组*先传元素个数再依次传各元素空数组用*0nil 数组用*-1。1.3 RESP3Redis 6.0——类型系统大升级Redis 6.0 引入 RESP3新增多种类型以支持更丰富的语义类型前缀名称用途示例_Null统一 nil 表示_| |#| Boolean | 布尔值 |#t/#f| |,| Double | 浮点数 |,3.14159| |(| Big Number | 大整数 |(349289352840923850932485094385094| |!| Bulk Error | 二进制安全错误 |!21ERR: 二进制错误内容| || Verbatim String | 原始文本带格式标记 |15txt:Some text| |%| Map | 键值对映射 |%2$3foo$3bar…| |~| Set | 无序集合 |~2$3foo$3bar || | | Attribute | 元数据属性 | |1key-popularity%2… || | Push | 服务端主动推送 | 3$7message… |RESP3 的核心改进类型语义化客户端无需猜测返回值类型如HGETALL返回 Map 而非 ArrayPush 类型支持服务端主动推送Pub/Sub、客户端缓存失效通知Null 统一RESP2 中 Bulk String 的$-1和 Array 的*-1都表示 nilRESP3 统一为_。2. 协议解析的底层实现与性能优化2.1 Redis 服务端的协议解析流程Redis 服务端通过readQueryFromClient读取客户端数据经processInputBuffer解析 RESP// networking.c 简化逻辑voidprocessInputBuffer(client*c){while(c-qb_possdslen(c-querybuf)){// 1. 查找第一个定位行尾char *newline strchr(c-querybuf c-qb_pos, ’);if (newline NULL) break; // 数据不完整等待更多数据// 2. 根据首字符判断类型调用对应解析函数 char type c-querybuf[c-qb_pos]; switch(type) { case *: processMultiBulkBuffer(c); break; // 数组命令 case $: processBulkBuffer(c); break; // 批量字符串 // ... 其他类型 } }}**关键优化**Redis 使用 **查询缓冲区querybuf** 累积数据避免每次读取都进行系统调用。c-qb_pos 记录已解析位置支持流式解析不完整的 RESP 数据。 - **2.2 零拷贝与内存优化** | 优化技术 | 实现方式 | 效果 | | -------- | -------- | ---- | | **查询缓冲区复用** | querybuf 采用 SDSSimple Dynamic String扩容时预分配额外空间 | 减少内存分配次数 | | **对象共享** | 小整数0~9999共享同一个 robj 对象 | 减少内存占用 | | **Pipeline 批量解析** | 一次 read 读取多个命令批量解析执行 | 减少系统调用和上下文切换 | | **RESP3 属性剥离** | \| 类型的 Attribute 数据不进入主回复流 | 减少客户端解析开销 | - **2.3 Pipeline 的协议层实现** Pipeline 不是 Redis 的新协议而是客户端的 **批量发送策略**客户端发送单次 write*3$3SET$4key1$6value1*3$3SET$4key2$6value2*2$3GET$4key1服务端返回单次 read 或多次 readOKOK$6value1**性能提升**Pipeline 将多个命令的 RTTRound-Trip Time从 N 次降为 1 次配合 TCP_NODELAY 禁用 Nagle 算法吞吐量可提升 10 倍以上。 ##### **3. Pub/Sub 与 RESP 协议的特殊交互** - **3.1 普通命令 vs Pub/Sub 的协议差异** | 模式 | 通信方向 | 协议类型 | 连接状态 | | ---- | -------- | -------- | -------- | | **普通命令** | 请求-响应 | RESP2/RESP3 | 无状态 | | **Pub/Sub** | 双向推送 | RESP2 Array / RESP3 Push | 进入 Pub/Sub 模式 | **RESP2 的 Pub/Sub 消息格式***3– 数组3 个元素$7– 第一个元素长度 7message– 消息类型message$5– 第二个元素长度 5mychannel– 频道名$7– 第三个元素长度 7hello!– 消息内容**RESP3 的改进**使用 Push 类型替代 * Array语义更清晰客户端可区分命令回复和服务端推送。 - **3.2 客户端缓存Client-Side Caching的 RESP3 支持** Redis 6.0 引入客户端缓存通过 RESP3 的 Push 类型发送键失效通知3– Push 类型3 个元素$10– 第一个元素长度 10invalidate– Push 类型invalidate*1– 第二个元素是数组1 个元素$4– 元素长度 4key1– 失效的键名客户端收到 invalidate 推送后从本地缓存中删除对应键实现近实时的缓存一致性。 ##### **4. 自定义客户端的协议解析陷阱** - **4.1 常见陷阱与正确做法** | 陷阱 | 错误做法 | 正确做法 | | ---- | -------- | -------- | | **行尾解析** | 用 分割忽略 | 严格匹配 处理 残留 | | **长度字段** | 用 int 解析长度 | 用 long longRedis 支持 512MB 的 Bulk String | | **二进制安全** | 用 C 字符串函数strlen处理内容 | 按长度字段精确读取内容可含 | | **嵌套解析** | 递归深度无限制 | 设置最大递归深度如 128防止恶意攻击 | | **内存分配** | 按长度字段直接 malloc | 限制单次分配上限防止 OOM 攻击 | | **不完整数据** | 假设每次 read 都能读到完整命令 | 维护解析状态机支持跨包解析 | - **4.2 协议解析状态机示例** c // 简化的 RESP 解析状态机 typedef enum { STATE_READ_TYPE, // 读取类型前缀 - : $ * 等 STATE_READ_LENGTH, // 读取批量长度$ 或 * 后的数字 STATE_READ_DATA, // 读取具体内容 STATE_READ_CRLF // 读取行尾 } ParseState; // 关键必须支持跨包解析 // 如果 read 只返回了 $6 foo需要缓存并等待下次 read 拿到 bar 5. RESP 与 Memcached 文本协议、HTTP/2 的对比协议类型特点适用场景RESP文本 二进制安全前缀标识符状态机解析极简实现Redis 专用高性能缓存Memcached 文本协议纯文本类似 HTTP命令 参数 Memcached简单但功能有限Memcached 二进制协议二进制固定头部 可变体高效Memcached减少解析开销HTTP/1.1文本通用、可扩展、人类可读Web 服务但解析开销大HTTP/2二进制多路复用、头部压缩、流控制现代 Web复杂但高效gRPC/Protobuf二进制强类型、IDL 定义、高效序列化微服务通信RESP 的独特优势在简单性和功能性之间取得了极致平衡。没有 HTTP 的复杂头部没有 gRPC 的强类型约束但比 Memcached 协议更丰富的类型系统。6. 面试官追问与高分回答模板追问 1“Redis 底层使用什么协议RESP 有哪些数据类型”低分回答“RESP 协议有简单字符串、错误、整数、批量字符串和数组五种。”没有区分 RESP2 和 RESP3高分回答Redis 底层使用RESPRedis Serialization Protocol协议目前有两个版本RESP2Redis 2.x~5.x定义了五种基础类型——Simple String、-Error、:Integer、$Bulk String、*Array。特点是前缀标识符 CRLF 分隔二进制安全任何语言 100 行代码即可实现客户端。RESP3Redis 6.0在 RESP2 基础上新增了 Boolean、Double、Big Number、Null、Bulk Error、Verbatim String、Map、Set、Push 等类型。核心改进是类型语义化客户端无需猜测返回值类型和服务端主动推送Push 类型支持 Pub/Sub 和客户端缓存失效通知。选型上Redis 6.0 默认使用 RESP3但客户端可通过HELLO 2降级到 RESP2。追问 2“RESP 协议为什么不用 JSON”低分回答“JSON 解析慢。”太笼统高分回答RESP 选择自定义协议而非 JSON基于四个工程权衡解析效率RESP 是前缀标识符 固定分隔符状态机解析即可O(1) 定位每行JSON 需要递归解析遇到嵌套对象时解析复杂度上升。二进制安全RESP 的 Bulk String 通过长度字段标识内容边界内容可以是任意二进制数据含 JSON 字符串必须转义控制字符不适合传输二进制数据如序列化后的 Java 对象。内存友好RESP 支持流式解析收到部分数据即可开始解析JSON 通常需要完整加载到内存才能解析除非用 SAX 风格解析器。实现简单RESP 客户端在任何语言中 100 行代码即可实现JSON 库通常数千行且不同语言实现差异大。当然代价是 RESP 是 Redis 专用协议不如 JSON 通用。追问 3“Pipeline 在协议层面是怎么实现的”低分回答“就是一次发送多个命令。”没有触及协议格式高分回答Pipeline 不是 Redis 的新协议而是客户端的批量发送策略。协议层面发送端客户端将多个 RESP 命令拼接成一个字节流通过单次write系统调用发送。例如两个 SET 命令拼接为*3 $3 SET $4 key1 $6 value1 *3 $3 SET $4 key2 $6 value2服务端Redis 单线程依次解析执行将多个回复放入输出缓冲区通过单次或多次write返回。性能收益将 N 个命令的 N 次 RTT 降为 1 次 RTT。配合TCP_NODELAY禁用 Nagle 算法吞吐量可提升 10 倍以上。注意Pipeline 只是减少网络往返不保证原子性。如果需要原子性用MULTI/EXEC或 Lua 脚本。追问 4“RESP3 相比 RESP2 有哪些重要改进”高分回答RESP3 是 Redis 6.0 引入的重大升级核心改进有三方面类型系统扩展新增 Boolean、Double、Big Number、Null、Map、Set 等类型。例如HGETALL在 RESP2 返回*4 ...数组客户端需按索引解析键值对RESP3 返回%2 ...Map语义更清晰。Push 类型服务端可主动向客户端推送消息。这是客户端缓存Client-Side Caching的基础——当缓存的键被修改时Redis 通过 invalidate推送通知客户端删除本地缓存。Null 统一RESP2 中 Bulk String 的$-1和 Array 的*-1都表示 nilRESP3 统一为_减少客户端判断逻辑。兼容性Redis 6.0 服务端同时支持 RESP2 和 RESP3客户端通过HELLO 2或HELLO 3协商版本。追问 5“自定义 Redis 客户端时协议解析有哪些陷阱”高分回答自定义客户端时RESP 解析有六个常见陷阱行尾匹配必须用 严格匹配不能只找 。某些实现中 残留会导致解析错位。长度字段越界Bulk String 的长度字段是十进制字符串需用 64 位整数解析。Redis 支持最大 512MB 的字符串32 位整数会溢出。二进制安全内容按长度字段精确读取不能用 C 的strlen或字符串函数处理因为内容可含 。嵌套深度限制数组可嵌套数组如*2 *2 ...必须设置最大递归深度如 128防止恶意客户端发送深层嵌套导致栈溢出。内存分配上限按长度字段malloc前必须限制上限防止$999999999这类攻击导致 OOM。跨包解析TCP 是流式协议单次read可能只收到部分 RESP 数据。必须维护解析状态机支持从中间状态恢复。追问 6“Redis 的 Pub/Sub 在协议层面是怎么实现的”高分回答Redis Pub/Sub 的协议实现分 RESP2 和 RESP3 两个阶段RESP2 阶段Pub/Sub 消息以*Array 类型发送。例如订阅mychannel后收到消息*3 $7 message $9 mychannel $5 hello三个元素分别是消息类型message/pmessage/subscribe、频道名/模式、消息内容。RESP3 阶段使用Push 类型替代*Array语义更清晰。客户端可明确区分’命令回复’和’服务端推送’。连接状态客户端执行SUBSCRIBE后连接进入 Pub/Sub 模式只能接收推送消息不能再发送普通命令除非使用SSUBSCRIBE和SUNSUBSCRIBE的 sharded Pub/Sub。协议限制Pub/Sub 消息不持久化、不确认网络闪断期间的消息会丢失。Redis 5.0 引入 Stream 作为更可靠的消息队列替代方案。7. 方案选型速查表业务场景推荐协议/模式核心理由注意事项简单 KV 读写RESP2/RESP3 普通命令简单直接高并发时用连接池批量操作无原子性要求Pipeline RESP2/3减少 RTT提升吞吐量命令数不宜过多避免阻塞批量操作需原子性MULTI/EXEC RESP2/3入队原子性避免运行时错误复杂原子计算Lua 脚本 RESP2/3执行原子性脚本不宜过长实时消息推送RESP3 Push 类型语义清晰支持客户端缓存消息不持久化跨语言服务通信不选 RESP用 gRPC/HTTPRESP 是 Redis 专用Redis 协议不适合通用 RPC自定义轻量客户端RESP2实现简单兼容性好注意跨包解析和内存安全面试官想要的满分总结Redis 底层使用RESPRedis Serialization Protocol协议其设计哲学是“极致的简单性换取极致的性能”。RESP2 通过 - : $ *五种前缀标识符实现了二进制安全、流式解析、极简实现RESP3 在此基础上扩展了类型系统引入 Push 类型支撑客户端缓存等高级特性。理解 RESP 不能停留在五种数据类型的表层而要深入到协议解析的零拷贝优化查询缓冲区复用、SDS 预分配、Pipeline 的批量发送原理单次 write 减少 RTT、以及自定义客户端的六个解析陷阱行尾匹配、长度越界、二进制安全、嵌套深度、内存上限、跨包解析。工程选型上简单操作用普通命令批量操作用 Pipeline原子操作用 Lua 脚本实时推送用 RESP3 Push。RESP 是 Redis 高性能的基石之一但它是专用协议不要试图将其泛化为通用 RPC 协议。觉得对您有帮助麻烦点点关注啦您的关注是我创作的最大动力~

相关新闻

frab 会议系统 API 完全指南:扩展与集成第三方服务

frab 会议系统 API 完全指南:扩展与集成第三方服务

frab 会议系统 API 完全指南:扩展与集成第三方服务 【免费下载链接】frab conference management system 项目地址: https://gitcode.com/gh_mirrors/fr/frab frab 是一款功能强大的会议管理系统(conference management system)&#…

2026/7/27 22:28:28 阅读更多 →
企业级应用开发架构优化:基于.NET 8与Vue 3的全栈低代码解决方案

企业级应用开发架构优化:基于.NET 8与Vue 3的全栈低代码解决方案

企业级应用开发架构优化:基于.NET 8与Vue 3的全栈低代码解决方案 【免费下载链接】Vue.NetCore (已支持sqlsugar).NetCore、.Net6、Vue2、Vue3、Vite、TypeScript、Element plusuniapp前后端分离,全自动生成代码;支持移动端(ios/android/h5/微…

2026/7/26 23:20:55 阅读更多 →
Windows Defender Remover终极指南:如何彻底移除系统自带杀毒软件

Windows Defender Remover终极指南:如何彻底移除系统自带杀毒软件

Windows Defender Remover终极指南:如何彻底移除系统自带杀毒软件 【免费下载链接】windows-defender-remover A tool which is uses to remove Windows Defender in Windows 8.x, Windows 10 (every version) and Windows 11. 项目地址: https://gitcode.com/gh_…

2026/7/26 23:20:56 阅读更多 →

最新新闻

USB屏幕驱动与树莓派应用:从原理到实战的嵌入式显示方案

USB屏幕驱动与树莓派应用:从原理到实战的嵌入式显示方案

1. 从“鸡肋”到“神器”:为什么你需要一块USB屏幕如果你玩过树莓派、PCduino或者Beaglebone这类单板计算机,大概率经历过这样的场景:项目调试到一半,需要临时改个配置或者看一眼日志,但手边没有多余的HDMI显示器&…

2026/7/28 4:26:15 阅读更多 →
基于Arduino与Processing的MPU6050传感器实时交互系统构建指南

基于Arduino与Processing的MPU6050传感器实时交互系统构建指南

1. 项目概述:当物理动作遇见数字光影几年前,我在一个创客展上看到一个装置,它只是一个简单的立方体框架,但当人们拿起它、摇晃它、旋转它时,内部的LED灯带就会流淌出变幻莫测的彩色光晕,仿佛把一块凝固的光…

2026/7/28 4:26:15 阅读更多 →
基于L298N与Mind+的直流电机闭环位置控制实战指南

基于L298N与Mind+的直流电机闭环位置控制实战指南

1. 项目缘起:从“仰”字说起的一次硬件复用探索最近在整理工作室的物料箱时,翻出来几块老朋友——DFRobot的DF-MD V1.3电机驱动模块,也就是大家熟知的L298N驱动板。看着它们,我忽然想起之前一个半途而废的项目:一个需要…

2026/7/28 4:26:15 阅读更多 →
Kimi K3本地部署与OpenCode集成:AI编程助手实战指南

Kimi K3本地部署与OpenCode集成:AI编程助手实战指南

在 AI 编程助手领域,OpenCode 和 Kimi K3 是近期备受开发者关注的两个工具。OpenCode 作为一个开源的 AI 编程辅助平台,提供了代码生成、解释、调试等功能,而 Kimi K3 作为其支持的重要模型之一,因其出色的代码理解和生成能力&…

2026/7/28 4:26:15 阅读更多 →
线性插值(lerp)原理与C/C++实现:从数学基础到工程实践

线性插值(lerp)原理与C/C++实现:从数学基础到工程实践

1. 项目概述:从“插值”到“平滑”的艺术在图形渲染、游戏开发、数据分析和音频处理这些领域里,我们经常遇到一个看似简单却至关重要的需求:如何在已知的两个点之间,平滑地计算出中间任意一点的值?比如,一个…

2026/7/28 4:26:15 阅读更多 →
TPIC7710EVM评估模块实战:从硬件解析到GUI软件驱动的电机控制评估

TPIC7710EVM评估模块实战:从硬件解析到GUI软件驱动的电机控制评估

1. 项目概述与核心价值在汽车电子,特别是车身控制模块和底盘电控系统的开发中,工程师面临一个核心挑战:如何将一颗功能复杂的专用集成电路从冰冷的规格书参数,快速转化为一个在真实车辆环境中稳定、可靠运行的子系统。规格书上的电…

2026/7/28 4:25:15 阅读更多 →

日新闻

告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生

告别臃肿!3步让你的暗影精灵笔记本重获新生 【免费下载链接】OmenSuperHub Control Omen laptop performance, fan speeds, and keyboard lighting, and unlock power limits. 项目地址: https://gitcode.com/gh_mirrors/om/OmenSuperHub 你是否也曾为官方Om…

2026/7/28 0:00:43 阅读更多 →
RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

RAG必踩坑!财报法规检索不准?这款开源工具让答案浮出水面,准确率飙升98.7%!

做 RAG 的人应该都踩过这个致命的坑:把几百页的财报、法规、技术手册扔给向量库,问一个具体问题,搜出来的全是沾边但没用的内容 —— 关键信息要么被硬切块拆碎了,要么藏在几十条结果的最下面。语义相似≠真正相关,这个…

2026/7/28 0:00:43 阅读更多 →
抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

抖音视频文案提取工具全指南:免费2026版、手机App、在线工具一网打尽

2026年做短视频运营,从抖音上扒文案早就不是偷偷抄笔记的事了。我刚开始做内容的时候,每天刷半小时抖音,手动把爆款视频的口播敲进备忘录,一条2分钟的视频得花十来分钟,碰到语速快的还要反复回听。后来试了一圈工具&am…

2026/7/28 0:00:43 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/27 4:33:59 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/27 6:31:56 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/27 4:01:12 阅读更多 →

月新闻