介绍Redis在客户端和服务端之间采用了一个独立的协议RESP(REdisSerializationProtocol)。笔者主要考虑以下几点:易于实现,阅读速度快注:RESP虽然是为Redis设计的,但也可以用于其他C/S软件。数据类型和示例RESP可以序列化以下类型:整数、单行回复(简单字符串)、数组、错误消息和多行字符串。Redis客户端发送给服务器的是一组执行命令组成的字符串数组,服务器根据不同的命令回复不同类型的数据,但协议的每一部分都以“rn”(CRLF)结尾。RESP也是二进制安全的,不需要处理从一个进程到另一个进程的传输,因为它使用前缀长度进行传输。在RESP中,有些数据的类型是通过它的首字节来判断的:单行回复:回复的首字节是“+”错误信息:回复的首字节是“-”整数数:回复的首字节是":"多行字符串:回复首字节为"$"数组:回复首字节为"*"单行回复以"+"开头,以"rn"结尾,以字符串形式结束.例如+OK\r\n响应客户端库应该返回“+”和CRLF以外的内容。例如上面的内容会返回“OK”。e.g.127.0.0.1:6379>setnameTaoBeier+OK\r\n#服务器实际返回---OK#redis-cli客户端显示错误信息错误信息类似单行回复,但是替换了"+”与“-”。两者真正的区别在于,错误信息被客户端视为异常,而构成错误类型的是错误信息本身。e.g.-错误信息\r\n只有在出现错误时才发送错误信息,例如数据类型错误、语法错误或命令不存在。相反,客户端库应该在收到错误消息时抛出异常。eg.127.0.0.1:6379>TaoBeier-ERRunknowncommand'TaoBeier'\r\n#服务器实际返回,下同---(error)ERRunknowncommand'TaoBeier'#redis-cli客户端显示,下同as127.0.0.1:6379>setnameTaoBeiermoelove-ERRsyntaxerror\r\n---(error)ERRsyntaxerror这种类型的整数只是用一个以“:”为前缀,以CRLF结尾的字符串来表示一个整数。例如“:666rn”或“:999rn”是整数回复。许多命令返回整数回复,例如INCRLLENLPUSH。但在大多数情况下,返回的整型回复并没有太大的实际意义。比如LPUSH只是表示插入了几个值,但也有EXISTS等命令,结果为真时返回1,假时返回0。例如127.0。0.1:6379>LPUSHinfoTaoBeierMoeLove:2\r\n#服务端实际返回,下同---(integer)2#Redis-cli客户端显示,下同127.0.0.1:6379>LLENinfo:2\r\n---(整数)2127.0.0.1:6379>存在信息:1\r\n---(整数)1127.0.0.1:6379>DEL信息:1\r\n---(integer)1127.0.0.1:6379>EXISTSinfo:0\r\n---(integer)0Multi-linestring服务器使用多行字符串返回一个最大长度为512MB的二进制安全字符串.以“$”开头,接着是要发送的实际字节数,然后是CRLF,然后是实际的字符串数据,最后以CRLF结尾。因此,例如,如果我们要发送一个字符串“moelove.info”,它实际上将被编码为“$12rnmoelove.infon”。而如果要发送一个空字符串,它将被编码为"$0rnrn"。在某些情况下,当一个值不存在时,它会返回“$-1rn”,这被称为一个空的多行字符串。当客户端库收到此响应时,它还应该返回一个空值(nil)而不是一个空字符串。eg.127.0.0.1:6379>setsitemoelove.info+OK\r\n#服务器实际返回,下同---OK#Redis-cli客户端显示,下同127.0.0.1:6379>get网站$12\r\nmoelove.info\r\n---"moelove.info"127.0.0.1:6379>delsite:1\r\n---(整数)1127.0.0.1:6379>获取网站$-1\r\n---(nil)127.0.0.1:6379>设置站点''+OK\r\n---OK127.0.0.1:6379>获取站点$0\r\n\r\n---""Array客户端可以使用数组类型向服务器发送命令。同样,某些命令组合元素返回给客户端时,也使用数组类型作为回复类型。它以“*”开头,后面是返回元素的数量,然后是CRLF,然后是数组中每个元素的类型。最典型的是LRRANGE命令,它返回列表中的元素。e.g.127.0.0.1:6379>LPUSHinfoTaoBeiermoelove.info:2\r\n#服务器实际返回,下同---(integer)2#Redis-cli客户端显示,下同127.0.0.1:6379>LRANGEinfo0-1*2\r\n$12\r\nmoelove.info\r\n$8\r\n淘贝尔\r\n---1)"moelove.info"2)"淘贝尔"127.0.0.1:6379>LPOPinfo$12\r\nmoelove.info\r\n---"moelove.info"127.0.0.1:6379>LPOPinfo$8\r\nTaoBeier\r\n---"TaoBeier"127.0.0.1:6379>LRANGEinfo0-1*0\r\n---(emptylistorset)综上所述,RESP协议还是比较容易理解的。另外,了解协议也便于定位Redis的一些问题和实现客户端。参考:RedisProtocolspecification可以通过下方二维码订阅我的文章公众号【MoeLove】
