Redis 的 RESP 协议

767 阅读3分钟

RESPRedis 客户端与 Redis 服务器相互通信时使用的一个协议, 全称 REdis Serialization Protocol ,即 redis 串行协议,通俗易懂,也表明了 redis 的特点,串行化(单线程)

注意: RESP 协议是一个应用层协议,也就是说它的底层还是依赖于 tcp/ip

RESP 的设计哲学

Redis 的作者在设计 RESP 协议,制定了下面的三条原则:

  1. 实现要简单
  2. 对计算机来说,解析速度快
  3. 对人类来说,可读性强

请求报文格式

Redis 客户端请求服务器时,报文格式非常简单,模板如下(注意:这里为了方便查看,CRLF 后面我还进行了手动换行,实际上是没有的)

*<参数数量>CRLF
$<参数1的字节长度>CRLF
<参数1的数据>CRLF
...
$<参数N的字节长度>CRLF
<参数N的数据>CRLF

其实就3个要素,参数的总个数,参数的字节长度、参数数据

例如,启动 redis-cli 客户端,发送一条命令:

set key1 value1

则这条命令对应的 RESP 协议报文内容为

*3CRLF$3CRLFsetCRLF$4CRLFkey1CRLF$6CRLFvalue1

为了方便我们人类查看,我将 CRLF 控制字符打印出来

*3
$3
set
$4
key1
$6
value1

附上注释

*3 //* 表示报文的开始,3 表示有三个参数,分别是 set、key1、value1
$3 // $3 表示第一个参数长度为 3 个字节
set  // 一个参数
$4 // 第二个参数长度为 4 个字节
key1 // 第二个参数
$6 // 第三个参数长度为 6 个字节
value1 // 第三个参数

客户端请求报文就是这么简单

响应报文格式

请求报文的格式只有一种,但响应报文的格式就多种多样了

简单字符串回复

简单字符串回复只有一行回复,回复的内容以 + 作为开头,不允许换行,并以 \r\n 结束。有很多指令在执行成功后只会回复一个 OK,使用的就是这种格式,能够有效的将传输、解析的开销降到最低。

例如上面的

set key1 value1

假设执行成功,返回报文为

+OKCRLF

错误回复

RESP 协议中,错误回复相当于简单字符串回复的变种形式,它们之间的格式也非常类似,区别只有第一个字符是以 - 作为开头,错误回复的内容通常是错误类型及对错误描述的字符串。

错误回复出现在一些异常的场景,例如当发送了错误的指令、操作数的数量不对时,都会进行错误回复。在客户端收到错误回复后,会将它视为异常。

例如

set1 key1 value1

由于没有 set1 这个命令,所以返回错误报文

-ERR unknown command `set1`, with args beginning with: `key1`, `value`,CRLF

整数回复

整数回复的报文非常简单

:数字CRLF

一般出现在用户执行 existsincrllen 等返回结果是数值或布尔类型的命令时,例如

exists key1

的回复报文为

:1CRLF

批量回复

批量回复的报文,模板如下

$<内容长度>CRLF
<内容>CRLF

它以 $ 作为开头,后面是发送的字节长度,然后是 CRLF,然后发送实际的数据,最终以 CRLF 结束。如果没有要回复的信息,那么回复长度为 -1。

举例

get key1

的回复报文为

$6CRLF
value1CRLF
get key2

的回复报文为

$-1CRLF

多条批量回复

多条批量回复的报文与客户端请求报文一模一样

*<参数数量>CRLF
$<参数1的字节长度>CRLF
<参数1的数据>CRLF
...
$<参数N的字节长度>CRLF
<参数N的数据>CRLF

多见于获取 hash、set、list 等类型的相关数据时,例如

lrange key2 0 -1

的回复报文为

*2
$3
123
$6
123456