听说Redis协议很简单,那今天就抓个包来一起看看吧。
RESP是什么
Redis 的序列化协议, 是一种二进制协议,支持多种数据类型,其中,数据的第一个字节(First byte)决定其类型,使用( CRLF
\r\n
)作为协议的终止符。特点:易于实现,快速解析,可直接阅读
目前有 RESP2 和 RESP3(Redis6开始) 两个版本。
支持这么多种类型 👇
RESP data type | Minimal protocol version | Category | First byte |
---|---|---|---|
Simple strings | RESP2 | Simple | + |
Simple Errors | RESP2 | Simple | - |
Integers | RESP2 | Simple | : |
Bulk strings | RESP2 | Aggregate | $ |
Arrays | RESP2 | Aggregate | * |
Nulls | RESP3 | Simple | _ |
Booleans | RESP3 | Simple | # |
Doubles | RESP3 | Simple | , |
Big numbers | RESP3 | Simple | ( |
Bulk errors | RESP3 | Aggregate | ! |
Verbatim strings | RESP3 | Aggregate | = |
Maps | RESP3 | Aggregate | % |
Sets | RESP3 | Aggregate | ~ |
Pushes | RESP3 | Aggregate | > |
下面开始会用 Linux 上的 nc 命令 和 Wireshark 来抓包部分命令进行分析。
简单字符串 和 整数
# 简单字符串
+OK\r\n
# 整数
:[<+|->]<value>\r\n
比如
:0\r\n和:1000\r\n
通过 nc 命令,连接到 Redis Server,可以清楚看到每一个指令。
:
表示整数
简单错误
-Error message\r\n
比如
-ERR unknown command 'asdf'
-WRONGTYPE Operation against a key holding the wrong kind of value
Bulk strings大字符串
$<length>\r\n<data>\r\n
比如
$5\r\nhello\r\n
$0\r\n\r\n
大字符串,支持 512 MB,可以通过 redis.conf 中的 proto-max-bulk-len 修改
针对 null 的情况
$-1\r\n
resp2的情况
从 Wireshark 中抓包可以看到,Response 5 个字节,$-1\r\n
resp3 设计了 Nulls 类型来处理 null
这里需要通过 hello 去升级协议,但是我 window 上 redis-cli 的版本比较低,不支持,会报错。
折腾了好一会,感觉在 window 上装这个 redis 超级麻烦,索性用 Nginx 去代理转发。
因为 Wireshark 装在 window 上,但是这个 redis 跑在虚拟机上的,如果直接连接 redis-server ,Wireshark 抓不到 VMnet8 网卡上的流量。
启用Nginx代理TCP流量
redis-cli 针对 null 解析成 nil 表示。
可以看到返回 3 个字节,_\r\n
刚好对上
数组
*
表示数组长度,这里是 6
$
是字符串长度,比如 name 是 4.
再比如 list 类型的。
lrange mylist 0 -1
Set
升级到 resp3 后,第一个字节是 ~
,对应上面的表格
没升级的情况还是数组的表示方式 *
用 Redis-cli 发出去的 Request 请求也是一样,比如这里 *2\r\n$8\r\nsmembers\r\n$5\r\nmyset\r\n
,刚好 29 个字节。
参考文章
https://redis.io/docs/latest/develop/reference/protocol-spec/ (官网文档)
https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md (官网文档)
暂无评论内容