#redis - https://redis.io/docs/latest/develop/reference/protocol-spec/ - 缩写:RESP - RESP 设计考量: - 易于实现 - 快速解析 - Human readable - 可以序列化不同的数据类型包含 intergers,strings 和 arrays,还支持 error 类型。 - client 的请求由一个 string 数组(array) 组成。 - 数据的元素包含请求的命令和参数。 - server 的回应类型则根据命令的不同而有所不同。 - 二进制安全(对于 bluk data 使用 prefiexed length) ---------- # RESP Versions - 第一版在 Redis 1.2 中韵如 - 第二版 RESP2 在 Redis 2.0 中称为通信的标准方式。 - 第三版 RESP3 是 RESP2 的超集, Redis 6.0 后引入。 - 引入 [HELLO](https://redis.io/docs/latest/commands/hello/) 命令用于协议握手商议。 - Redis 7 后,RESP2 和 RESP3 的客户端都可以调用所有核心命令。 - 但是 不同协议版本可能会有**不同**的回复类型。 --------- # Request-Response model - Redis 命令是一个简单的 Request-Response 模型,但有一些例外: - Redis 请求支持 **pipeline**,client 可以一次性发送多个命令。 - 当一个 RESP2 连接订阅一个 Pub/Sub channel 后,协议会变成 **Push** 形式。 - client 不需要再发生命令,server 会自动发送新消息给 client。 - **MONITOR** 命令调用后,连接切换成 ad-hoc push 模型。 - **Protected mode**。在该模式下来自非本地的连接会被拒绝,发送一个 DENIED reply。 - **RESP3 Push type**。允许 server 随时发送 out-of-band data,无需关联与 client 发送的命令。 ---------- # RESP protocol description - 第一个字节决定数据的类型。 - request-response 格式 - client request 是一个 bulk string 的数组(array) - array 中的第一个 string 是命令/ COMMAND - 其余为命令的参数 - server 回应一个 RESP type。具体类型取决于命令和协议版本。 - CRLF(`\r\n`) 是协议的**终止符**,即一个 RESP type 的结束符号 - RESP data type 可以分为三类: - **Simple** 类似与编程语言中的 scalars,例如布尔和整型。 - **Bulk** string 可以是 simple 或者 bulk 类型的。 - simple string 不能包含 `\r` 和 `\n` 字符 - bulk 可以包含任意字符 - **Aggregate** 例如 Arrays 和 Maps,可以有不同数据的子元素和嵌套层次。 |RESP data type|Minimal protocol version|Category|First byte| |---|---|---|---| |[Simple strings](https://redis.io/docs/latest/develop/reference/protocol-spec/#simple-strings)|RESP2|Simple|`+`| |[Simple Errors](https://redis.io/docs/latest/develop/reference/protocol-spec/#simple-errors)|RESP2|Simple|`-`| |[Integers](https://redis.io/docs/latest/develop/reference/protocol-spec/#integers)|RESP2|Simple|`:`| |[Bulk strings](https://redis.io/docs/latest/develop/reference/protocol-spec/#bulk-strings)|RESP2|Aggregate|`
| |[Arrays](https://redis.io/docs/latest/develop/reference/protocol-spec/#arrays)|RESP2|Aggregate|`*`| |[Nulls](https://redis.io/docs/latest/develop/reference/protocol-spec/#nulls)|RESP3|Simple|`_`| |[Booleans](https://redis.io/docs/latest/develop/reference/protocol-spec/#booleans)|RESP3|Simple|`#`| |[Doubles](https://redis.io/docs/latest/develop/reference/protocol-spec/#doubles)|RESP3|Simple|`,`| |[Big numbers](https://redis.io/docs/latest/develop/reference/protocol-spec/#big-numbers)|RESP3|Simple|`(`| |[Bulk errors](https://redis.io/docs/latest/develop/reference/protocol-spec/#bulk-errors)|RESP3|Aggregate|`!`| |[Verbatim strings](https://redis.io/docs/latest/develop/reference/protocol-spec/#verbatim-strings)|RESP3|Aggregate|`=`| |[Maps](https://redis.io/docs/latest/develop/reference/protocol-spec/#maps)|RESP3|Aggregate|`%`| |[Attributes](https://redis.io/docs/latest/develop/reference/protocol-spec/#attributes)|RESP3|Aggregate|`| |[Sets](https://redis.io/docs/latest/develop/reference/protocol-spec/#sets)|RESP3|Aggregate|`~`| |[Pushes](https://redis.io/docs/latest/develop/reference/protocol-spec/#pushes)|RESP3|Aggregate|`>`| ## Simple strings - 加号 `+` 开头,后跟 string,string 不能包含 `\r` 和 `\n` ,以 CRLF 结尾 ``` +OK\r\n ``` ## Simple errors - 类似 simple string,但起始字符为 `-` 减号,string 内容为错误信息。 ``` -Error message\r\n ``` - server error replies 示例 ``` -ERR unknown command 'asdf' -WRONGTYPE Operation against a key holding the wrong kind of value ``` - error prefix:减号后面的第一个大小单词表示错误的种类(这是 redis 的惯例,而非协议强制要求) - ERR 是一个通用的错误类型 ## Intergers - 代表 64 位有符号的十进制整数。 - 格式: ``` :[<+|->]<value>\r\n ``` - 起始:冒号 - 符号位(可选):加号或减号 - 多个 0..9 数字 - CRLF 结尾 - 例: - `:0\r\n` 表示数字 0 - `:1000\r\n` 表示数字 1000 - 使用场景: - 许多命令的回复都是数字,例如`INCR`,`LLEN` ,`LASTSAVE` - 有些场景也可以表示 true 或 false - 例如 `SISMEMBER` 返回 1 表示 true,0 表示 false - 有些命令使用数字表示数据是否变更 - 如 `SADD`,`SREM`,`SETNX` ## Bulk strings - 表示二进制字符串,支持任意大小。(但是Redis 默认限制位 512 MB)。 - 格式: ``` lt;length>\r\n<data>\r\n ``` - 起始字符为 `
- 一到多个 0..9 数字表示字符串的长度(无符号10进制) - CRLF 分割符表示长度结束 - 字符串内容 - CRLF结尾 - 例: - Hello: `$5\r\nhello\r\n` - 空字符串:`$0\r\n\r\n` ## Arrays - 表示一组元素的集合。 - 格式 ``` *<number-of-elements>\r\n<element-1>...<element-n> ``` - 起始字符为 `*` - 一到多个数字表示元素的个数 - CRLF 分割符 - 后跟 N 个元素,每个元素是一个 RESP type。 - 每个元素的 type 可以**不同**。 - 支持嵌套,例如元素可以是另一个 array。 - 例: - `*0\r\n`:空数组 - `*2\r\n$5\r\nhello\r\n$5\r\nworld\r\n`:包含 "hello" 和 "word" 两个字符串 ---------------------------------