news 2026/5/19 19:26:50

Redis通信协议-RESP协议

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Redis通信协议-RESP协议

一、前言:高效通信的基石

当我们使用redis-cli执行一条SET name "Redis"命令时,背后发生了一系列精妙的通信过程。客户端如何告诉服务器它想执行什么命令?服务器又如何将“OK”这个结果准确无误地返回给客户端?

这一切的奥秘,都藏在 Redis 自研的通信协议——RESP(REdis Serialization Protocol)之中。

RESP 协议是 Redis 客户端与服务端之间沟通的“通用语言”。理解它,不仅能让你更深刻地认识 Redis 的工作原理,还能帮助你从零开始实现一个自己的 Redis 客户端!

💡核心价值
RESP 协议以其简单、高效、可读性强和二进制安全的特性,成为了 Redis 高性能的基石之一。本文将带你彻底掌握 RESP 协议的五种数据类型、编码规则以及完整的请求-响应流程


二、RESP 协议简介

2.1 什么是 RESP?

RESP 全称REdis Serialization Protocol(Redis 序列化协议)。它由 Redis 作者 Salvatore Sanfilippo 设计,于 Redis 1.2 版本引入,并在 Redis 2.0 中成为标准通信协议。

虽然它是为 Redis 量身定制的,但其简洁的设计使其完全可以应用于其他客户端-服务器(C/S)软件项目。

2.2 核心设计哲学

  • 简单性:协议格式直观,易于人类阅读和程序解析。
  • 高效性:解析开销极低,无需复杂的词法或语法分析器。
  • 二进制安全:能够安全地传输任何二进制数据,不会因为特殊字符(如\r\n)而产生歧义。
  • 可扩展性:支持多种数据类型,能表达复杂的嵌套结构。

三、RESP 的五种数据类型

RESP 协议通过在每条消息的开头使用一个特定的字节来标识其数据类型。共有五种基本类型:

类型首字节描述示例
简单字符串 (Simple Strings)+用于表示非二进制安全的简单状态或成功消息。不能包含\r\n+OK\r\n
错误 (Errors)-用于返回错误信息。本质上也是一种字符串,但客户端应将其视为异常。-ERR unknown command 'FOO'\r\n
整数 (Integers):用于表示有符号的64位整数。:1000\r\n
批量字符串 (Bulk Strings)$最常用!用于表示二进制安全的单个字符串,可以包含任意数据,包括空值 (null)。$5\r\nhello\r\n
$-1\r\n(表示 null)
数组 (Arrays)*用于表示元素列表,元素可以是任意 RESP 数据类型,包括嵌套数组。*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n

⚠️注意:所有 RESP 消息都以\r\n(CRLF) 结尾。


四、深度解析:每种类型的编码规则

4.1 简单字符串 (Simple Strings)

  • 格式+<字符串>\r\n
  • 用途:通常用于返回简单的状态码,如OK
  • 限制:不能包含换行符,因此不适用于传输任意数据。
// 服务器响应 +OK\r\n

4.2 错误 (Errors)

  • 格式-<错误信息>\r\n
  • 用途:当服务器遇到错误时返回。客户端库通常会将此转换为异常抛出。
  • 惯例:错误信息通常以错误码开头,如ERR,WRONGTYPE
// 服务器响应 -ERR Operation against a key holding the wrong kind of value\r\n

4.3 整数 (Integers)

  • 格式:<数字>\r\n
  • 用途:返回整数值,如INCR命令的结果、LLEN返回的列表长度等。
// 服务器响应 :42\r\n

4.4 批量字符串 (Bulk Strings) -重点

  • 格式
    • 非空字符串:$<长度>\r\n<数据>\r\n
    • 空字符串:$0\r\n\r\n
    • Null 值:$-1\r\n
  • 用途:这是传输实际数据(如 key, value)的主要方式,因为它二进制安全
  • 优势:通过前置长度,接收方可以精确地知道要读取多少字节,无需寻找终止符,效率极高。
// 传输 "hello" $5\r\nhello\r\n // 传输一个包含换行符的二进制数据 "\r\n" $2\r\n\r\n\r\n // 表示 GET 一个不存在的 key $-1\r\n

4.5 数组 (Arrays) -重点

  • 格式*<元素数量>\r\n<元素1><元素2>...<元素N>
  • 用途客户端发送的所有命令都是以数组形式编码的!同时,服务器返回复杂结果(如LRANGE,HGETALL)也用数组。
  • 灵活性:数组中的每个元素可以是任意 RESP 类型,支持嵌套。
// 客户端发送命令: SET mykey "Hello World" *3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$11\r\nHello World\r\n // 服务器响应 LRANGE list 0 -1 (假设list有两个元素 "a", "b") *2\r\n$1\r\na\r\n$1\r\nb\r\n // 服务器返回一个空列表 *0\r\n

五、一次完整的通信流程

让我们通过GET mykey这个简单命令,走完一次完整的客户端-服务器交互。

5.1 客户端 -> 服务器 (请求)

客户端需要将命令序列化为一个Bulk String 数组

  • 命令本身是一个字符串"GET"
  • 参数mykey是另一个字符串

因此,请求被编码为:

*2\r\n$3\r\nGET\r\n$5\r\nmykey\r\n

分解:

  • *2:这是一个包含 2 个元素的数组。
  • $3\r\nGET\r\n:第一个元素,长度为 3 的字符串 "GET"。
  • $5\r\nmykey\r\n:第二个元素,长度为 5 的字符串 "mykey"。

5.2 服务器 -> 客户端 (响应)

假设mykey的值是"Hello",服务器会返回一个 Bulk String。

$5\r\nHello\r\n

如果mykey不存在,则返回 Null Bulk String:

$-1\r\n

六、为什么选择文本协议?

很多人可能会疑惑:文本协议不是比二进制协议更“浪费”带宽吗?为什么高性能的 Redis 要选择它?

Redis 作者对此有清晰的解释:

  1. 瓶颈不在网络:对于内存数据库而言,真正的瓶颈是 CPU 处理命令的逻辑和内存带宽,而非网络传输的数据量。节省几个字节的协议头带来的收益微乎其微。
  2. 极致的简单性:文本协议极大地简化了客户端和服务器的实现与调试。你可以直接用telnetnc连接到 Redis 服务器并手动输入命令进行测试!
  3. 可读性强:在抓包分析或日志记录时,文本协议的内容一目了然,无需额外的解析工具。

这种“在非瓶颈处做简单设计”的哲学,正是 Redis 成功的关键因素之一。


七、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/18 15:35:21

深入解析Enso:构建高性能可编程代理与API网关的Go框架

1. 项目概述&#xff1a;一个被低估的“瑞士军刀”如果你在开源社区里混迹过一段时间&#xff0c;大概率见过这样的场景&#xff1a;一个项目仓库&#xff0c;名字起得挺酷&#xff0c;比如“Enso”&#xff0c;简介里写着“一个现代化的代理工具”&#xff0c;但点进去一看&am…

作者头像 李华
网站建设 2026/5/18 15:34:34

3步掌握League Akari:英雄联盟玩家的智能工具箱完整指南

3步掌握League Akari&#xff1a;英雄联盟玩家的智能工具箱完整指南 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power &#x1f680;. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit League Akari是一款基于英…

作者头像 李华
网站建设 2026/5/18 15:34:27

TC264智能车循迹进阶:从八邻域到逐行遍历,实战解析赛道边界提取算法

1. 智能车循迹技术基础与挑战 玩过智能车竞赛的朋友都知道&#xff0c;循迹是最基础也最核心的功能。早期的简单中线循迹法&#xff0c;就像新手开车只会盯着马路正中间走&#xff0c;遇到岔路或环岛就懵了。我在最初参赛时就吃过这个亏——小车在直道上跑得飞快&#xff0c;一…

作者头像 李华
网站建设 2026/5/18 15:30:41

会话包装器设计:提升API连接弹性与可观测性的工程实践

1. 项目概述&#xff1a;一个被低估的会话管理利器如果你经常和API打交道&#xff0c;尤其是那些需要维护会话状态的服务&#xff0c;肯定遇到过这样的烦恼&#xff1a;每次请求都要手动处理token、处理重连逻辑、管理超时和重试&#xff0c;代码里到处都是重复的胶水代码。更头…

作者头像 李华
网站建设 2026/5/18 15:30:01

基于Hugo与DevOps的现代化静态博客搭建与优化实战

1. 项目概述&#xff1a;一个开源博客的诞生与演进最近在整理自己的技术栈&#xff0c;翻到了几年前搭建个人博客时用到的cnych/qikqiak.com这个项目。这其实是一个基于 Hugo 静态生成器构建的博客站点源码&#xff0c;托管在 GitHub 上。对于很多开发者来说&#xff0c;拥有一…

作者头像 李华