Redis通信机制:简介RESP协议

RESP(Redis serialization protocol)是Redis客户端与服务端通信的协议。本文简单介绍了RESP协议的内容。官方文档

简述

RESP支持传输五种数据:简单字符串、错误、整数、大容量字符串和数组。

当客户端向服务器发送请求时,将命令存放在数组中;对于这些命令,服务端返回以上五种数据中的一种作为响应。

在RESP中,第一个字节确定了数据类型:

  • 简单字符串:+
  • 错误:-
  • 整数::
  • 大容量字符串:$
  • 数组:*

RESP可以使用大容量字符串或数组的特殊形式作为Null值。

在RESP中,消息总是以\r\n结尾。

简单字符串

简单字符串以+开头,不准出现\r\n(只能有一行),以\r\n结尾。

简单字符串用于以最小开销表示简单数据。例如,对于OK消息,它的编码为:

1
"+OK\r\n"

简单的字符串是二进制不安全的。如果需要加密,使用大容量字符串。

当客户端收到简单字符串时,应当以字符串内容作为响应。它包括除了+CRLF以外的内容。

错误

错误消息类似于简单字符串,它以-开头,后跟的数据为错误消息。

1
"-Error message\r\n"

只有当出现异常时才应该发送错误消息。为了方便,从-到第一个空格或结尾的字符串表示错误的类型,称为错误前缀,使得接收方能够区分错误的类型。

1
2
"-ERR unknown command 'helloworld'"
"-WRONGTYPE Operation against a key holding the wrong kind of value"

整数

整数的格式为:后跟一个数字,这个数字必须在64位有符号整数的表示范围内。

除了用来传输数字,整数还可以作为消息执行成功与否的回应,或用来表示布尔值。有一些指令规定使用数字作为回复,如INCRLLEN等。

大容量字符串

大容量字符串可以用于传输二进制安全的,最大512MB的字符串。它按如下方式编码:

  • $是第一个字节的内容,后跟一个数字,表示字符串的长度(单位为字节),以CRLF结尾。
  • 实际内容
  • 结尾的CRLF

例如

1
"$5\r\nhello\r\n"

空字符串表示为

1
"$0\r\n\r\n"

要用大容量字符串表示空值,只需要将前缀长度设置为-1,例如

1
"$-1\r\n"

数组

客户端使用数组向服务端发送指令。当服务器需要返回一系列数据时,使用数组作为响应,例如LRANGE

数组的格式为:

  • 第一个字节是*,后跟一个数字表示数组元素的数量,以CRLF结尾。
  • 后跟附加的元素。对于每一个元素,其格式参考之前的内容。

一个空数组的格式为:

1
"*0\r\n"

["hello", "world"]表示为:

1
"*2\r\n$5\r\nhello\r\n$5\r\nworld\r\n"

数组可以保存不同类型的数据,例如

1
2
3
4
5
6
7
*5\r\n
:1\r\n
:2\r\n
:3\r\n
:4\r\n
$5\r\n
hello\r\n

数组同样可以表示为Null值:

1
*-1\r\n

数组支持层次结构,例如,由两个数组组成的一个数组可以表示为:

1
2
3
4
5
6
7
8
*2\r\n
*3\r\n
:1\r\n
:2\r\n
:3\r\n
*2\r\n
+Hello\r\n
-World\r\n

向Redis服务端发送命令

客户端使用数组类型向服务端发送指令,且指令中所有字符串都是大容量字符串;服务端可以向客户端发送任意数据。

例如,客户端向服务器端发送指令LLEN mylist

1
2
3
4
5
6
7
C: *2\r\n
C: $4\r\n
C: LLEN\r\n
C: $6\r\n
C: mylist\r\n

S: :48293\r\n

多个指令与流水线

RESP支持流水线机制,客户端可以使用相同的连接发送多个指令。

内置指令

Redis支持一些内置指令,这些指令只需要通过TCP发送,不需要使用客户端。

1
2
C: PING
S: +PONG