Redis客户端使用为名为RESP(Redis序列化协议)的协议与Redis服务器进行通信。虽然该协议是专门为Redis设计的,但它也可以用于其他的CS软件项目的通信协议。
RESP可以序列化不同的数据类型,如整型,字符串,数组。 还有⼀种特定的错误类型。 请求将要执行的
命令作为字符串数组从Redis客户端发送到Redis服务器。Redis使用特定数据类型的命令进行回复。
RESP是二进制安全的,不需要处理从⼀个进程传输到另⼀个进程的批量数据,因为它使用前缀长度来传输
批量数据。
注:该协议仅用于客户端——服务器通信。 Redis Cluster使用不同的二进制协议,以便在节点之间交换信息。
网络层
客户端通过TCP连接到端口6379,虽然RESP在技术上是非TCP特定的,但是在Redis上下文中,协议仅用于TCP连接。
请求——相应模型
Redis接受不同参数组成的命令。这是最简单的模型,但有两个例外:
- Redis支持流水线操作。因此,客户端可以一次发送多个命令,并等待稍后的回复。
- Redis客户端处于Pub/Sub时,协议会更改语义并成为推送协议,即客户端不再发送命令,因为服务器会在它们接收到命令时自动向客户端发送新消息。
RESP协议描述
RESP协议在Redis1.2中引入,在2.0中称为Redis服务器通信的标准方式。
支持以下类型:单行字符串、错误信息、整型、多行字符串和数组。
RESP根据通过数据的第一个字节判断它的类型:
- 单行(Simple Strings)回复:“+”
- 错误(Errors)信息:“-”
- 整型数字(Integers):“:”
- 多行字符串(Bulk Strings): “$”
- 数组(Arrays): “*”
RESP中,协议的不同部分始终以"\r\n"结束。
注:执行同样的命令,错误和正确的返回类型可能相同也可能不相同。
- SETNX错误和正确的返回类型一致(Integers),都是以整数的形式返回。
- INCR错误的时候返回错误信息(Errors),正确的时候返回整型(Integers)。
RESP 单行字符串(+ Simple Strings)
简单字符串按以下方式编码:+号字符,后跟不能包含CR或LF字符的字符串(不允许换行),由CRLF终
止(即“\ r \ n”,对应十六进制 0x0D,0x0A)。
Simple Strings用于以最小的开销传输非⼆进制安全字符串。 例如,很多Redis命令成功回复时只
有“OK”,因为RESP 单行字符串使用以下5个字节进行编码:
"+OK\r\n"
RESP 错误信息(- Errors)
RESP中单行字符串和错误之间的真正区别在于客户端将错误视为异常,组成错误类型的字符串是错误消息
本身。
基本格式如下:
"-Error message\r\n"
错误回复仅在发生错误时发送,例如,如果您尝试对错误的数据类型执⾏操作,或者命令不存在等等。 收
到错误回复时,客户端应将异常抛出。
以下是错误回复的实例:
-ERR unknown command 'foobar'
-WRONGTYPE Operation against a key holding the wrong kind of value
“-”之后的第⼀个单词,直到第⼀个空格或换行符,表示返回的错误类型。 这只是Redis使用的约定,不是
RESP错误格式的⼀部分。
例如,ERR是⼀般错误,而WRONGTYPE是⼀个更具体的错误,意味着客户端尝试对错误的数据类型执行
操作。 这称为错误前缀,是⼀种允许客户端理解服务器返回的错误类型的方法,而不依赖于给定的确切消
息,这可能随时间而变化。
客户端实现可以针对不同的错误返回不同类型的异常,或者可以通过直接将错误名称作为字符串提供给调
用者来提供捕获错误的通用方法。
但是,这样的功能不应该被认为是至关重要的,因为它很少有用,并且有限的客户端实现可能只返回通用
的错误条件,例如false。
127.0.0.1:6379> SET teacher darren
OK
127.0.0.1:6379> INCR teacher
(error) ERR value is not an integer or out of range
RESP 整型数据(: Integers)
此类型只是⼀个CRLF终止的字符串,表示⼀个以“:”字节为前缀的整数。 例如“:0\r\n”或“:1000\r\n”是整数回复。
许多Redis命令返回RESP 整型,如INCR, LLEN 和LASTSAVE。返回的整数没有特殊含义,它只是INCR的增量值,LASTSAVE的UNIX时间等等。 但是,返回的整数应保证在有符号的64位整数范围内。
整数回复也被广泛使用,以便返回真或假。 例如,EXISTS或SISMEMBER之类的命令将返回1表示true,0表示false。如果实际执行操作,其他命令(如SADD,SREM和SETNX)将返回1,否则返回0。
以下命令将回复整数回复:SETNX,DEL,EXISTS,INCR,INCRBY,DECR,DECRBY,DBSIZE,LASTSAVE,RENAMENX,MOVE,LLEN,SADD,SREM,SISMEMBER,SCARD。
RESP 多行字符串($ Bulk Strings)
多行字符串用于表示长度最大为512MB的单个二进制安全字符串。
多行字符串按照以下方式编码:
- 一个"$"字节后跟组成字符串的字节数(一个前缀长度),由CRLF终止。
- 字符串数据。
- 最终的CRLF。
示例如下:
"$6\r\nfoobar\r\n"
"$0\r\n\r\n"
"$-1\r\n"
最后一种特殊格式表示Null值,不存在。
RESP 数组(* Arrays)
客户端使⽤RESP 数组将命令发送到Redis服务器。 类似地,某些Redis命令将元素集合返回给客户端使用RESP 数组是回复类型。 ⼀个例子是LRANGE命令,它返回列表的元素。
RESP数组使用以下格式发送:
- *字符作为第一个字节,后跟数组中的元素个数作为十进制数,后跟CRLF。
- 数组的每个元素的附加RESP类型。
"*0\r\n"
"*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n"
"*3\r\n:1\r\n:2\r\n:3\r\n"
发送命令到Redis服务端
- 客户端向Redis服务器发送仅有Bulk Strings组成的RESP阵列。
- Redis服务器回复发送任何有效的RESP数据类型作为客户端的恢复。
比如客户端发送命令LLEN mylist
以获取存储在密钥mylist
中的列表长度,服务器回复一个Integer
如下所示:C是客户端,S是服务器
C: *2\r\n
C: $4\r\n
C: LLEN\r\n
C: $6\r\n
C: mylist\r\n
S: :48293\r\n
通常我们将协议的不同部分与换行符分开以化简,但是实际的交互是客户端发送* 2 \ r \ n $ 4 \ r \n LLEN \ r \ n $ 6 \ r \ nmylist \ r \ n整体。
最后给大家推荐一个LinuxC/C++高级架构系统教程的学习资源与课程,可以帮助你有方向、更细致地学习C/C++后端开发,具体内容请见 https://xxetb.xetslk.com/s/1o04uB