redis的通信协议(protocol)
Redis客户端使用名为RESP(REdis序列化协议)的协议与Redis服务器通信。虽然该协议是专为Redis设计的,但它可以用于其他客户端-服务器软件项目
RESP是以下事项之间的妥协:易于实施、快速解析、人类可读
RESP实际上是一个支持以下数据类型的序列化协议:简单字符串,错误,整数,批量字符串和数组。
RESP是二进制安全的,不需要处理从一个进程传输到另一个进程的批量数据,因为它使用前缀长度来传输批量数据
注意:此处概述的协议仅用于客户端 - 服务器通信。Redis Cluster使用不同的二进制协议,以便在节点之间交换消息
虽然RESP在技术上是非TCP特定的,但在Redis的上下文中,协议仅用于TCP连接或类似的面向流的连接(如Unix套接字)
客户端和服务器发送的命令或数据一律以\r(CRLF)结尾
请求协议:
新版统一请求协议在Redis 2.0版本成为Redis服务器通信的标准方式。在这个协议中,所有发送至Redis服务器的参数都是二进制安全(binary safe)的。
以下是这个协议的一般形式:
*<参数数量> CR LF $<参数 1 的字节数量> CR LF <参数 1 的数据> CR LF ... $<参数 N 的字节数量> CR LF <参数 N 的数据> CR LF 注:命令本身也作为协议的其中一个参数来发送
举个例子:
命令set mykey myvalue的请求协议为
命令set mykey myvalue的请求协议为 *3 $3 SET $5 mykey $7 myvalue 这个命令的实际协议值如下: "*3\r$3\rSET\r$5\rmykey\r$7\rmyvalue\r"
回复协议:
Redis命令会返回多种不同类型的回复。通过检查服务器发回数据的第一个字节,可以确定这个回复是什么类型:
简单字符串(Simple Strings)的第一个字节是 "+" 错误(Errors)的第一个字节是 "-" 整数(Integers)的第一个字节是 ":" 增大字符串(Bulk Strings)的第一个字节是 "$" 数组(Arrays)的第一个字节是 "*"
简单字符串回复
简单字符串回复按以下方式编码:加号字符("+"),后跟不能包含CR或LF字符的字符串(不允许换行),由CRLF终止("\r")
简单字符串回复用于以最小的开销传输非二进制安全字符串,通常由那些不需要返回数据的命令返回
当Redis使用简单字符串回复时,客户端库应该向调用者返回一个字符串,该字符串由‘+‘之后的第一个字符开始,直到字符串结尾,不包括最终的CRLF字节
如:"+OK\r",客户端就应该返回字符串"OK"
错误回复
错误回复和简单字符串回复非常相似, 不同的是错误回复的第一个字节是"-"
客户端库应该在收到错误回复时产生一个异常。
基本格式是:"-ERR/WRONGTYPE message\r"
在"-"之后,直到遇到第一个空格或新行为止,这中间的内容表示所返回错误的类型(这只是Redis使用的约定,不是RESP错误格式的一部分)。
ERR是一个通用错误类型,而WRONGTYPE则是一个更特定的错误类型。
客户端可以为不同类型的错误产生不同的异常,或者提供一种通用的方式,让调用者可以通过提供字符串形式的错误名来捕捉不同的错误。
整数回复
整数回复就是一个以":"开头,字符串表示的整数在中间,CRLF结尾的字符串表示的整数。
返回值的唯一限制是返回的整数保证在有符号的64位整数范围内。
被返回的整数没有什么特殊的含义, 如:INCR返回键的一个自增后的整数值,而LASTSAVE则返回一个UNIX时间戳
整数回复也被广泛地用于表示逻辑真和逻辑假: 如返回值1表示真,0表示假
还有一些命令,只在操作真正被执行了的时候(如SADD、SREM和SETNX),才返回1,否则返回0
以下命令都返回整数回复: SETNX、DEL、EXISTS、INCR、INCRBY、DECR、DECRBY、DBSIZE、LASTSAVE、RENAMENX、MOVE、LLEN、SADD、SREM、SISMEMBER、SCARD
增大字符串回复(Bulk Strings)
Bulk Strings用于表示长度最大为512MB的单个二进制安全字符串,如get命令
增大字符串按回复以以下方式编码:
第一字节为 "$" 符号 接下来跟着的是表示实际回复长度的数字值 之后跟着一个CRLF 再后面跟着的是实际字符串数据 最末尾是另一个 CRLF
如果被请求的值不存在, 那么特殊值-1用作回复的长度值,并且没有数据:"$-1\r",这种回复称为空增大字符串(Null Bulk String)。
当服务器使用Null Bulk String回复时,客户端应该返回空对象(nil),而不是空字符串。
数组回复
数组回复类型将元素集合返回给客户端。如LRANGE命令
数组回复是由多个回复组成的,数组中的每个元素都可以是任意类型的回复
数组回复的第一个字节为"*",后跟一个字符串表示回复元素数量的整数值,再后面是一个CRLF,再后面跟着的则是回复的所有元素
*3 $3 foo :7 $5 Hello
空白的数组回复:"*0\r",如lrange一个不存在的key
无内容的数组回复:"*-1\r",如命令超时
客户端库应该区别对待空白多条回复和无内容多条回复: 当Redis返回一个无内容多条回复时,客户端库应该返回一个null对象,而不是一个空数组