#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" 两个字符串
---------------------------------