本篇文章针对的是
redis RESP2
协议分析
整体分析
从整体角度来看,redis
客户端和服务端交互其实就两个:
- 客户端发送:
- 命令
- 缓存键,缓存值
- 服务端发送:
- 返回给客户端的结果
- 获取成功的
OK
标志「字符串」 - 成功写入的元素个数
- 错误信息「
ERR
」
从整体来讲,交互内容分为以下几个点:
- 命令:
Set, Get
- 缓存键:
Set key value
中的key
,只能是字符串; - 缓存单个值:
Set key value
中的value
。字符串,数字,一般是这些; - 缓存集合:
HSet key value1 value2
。缓存多个值的时候,传输的可能是不同类型的值; OK
:命令执行成功,返回一个OK
回复;Int
:写入N个元素成功,返回N
对应的int值ERR
:错误信息
上面是命令的形式,下面我们讨论一下交互的数据:
首先 RESP
底层走的是 TCP
,最需要的考虑的问题之一就是粘包拆包,那么 redis server
如何区分出正确的包呢?通常3种方法:
- 数据包固定长度,不足不全,超过截断
- 分隔符区分,
HTTP
就是用换行符区分的 - 数据包头部设置数据长度
自定义协议
redis
采取的是自定义协议格式区分不同命令请求,举个例子:
SET key value
=>
*3\r\n$3\r\nSET\r\n$9\r\nkey\r\n$6\r\nvalue\r\n
复制代码
一时间看不懂这是啥,区分解释一下:
\r\n
:分隔符*3
:命令有3个参数$3...
:当前参数的字符串长度
其实就是先区分发送字符边界,然后确定发送分送了多少字符串,然后是每一个字符串有多长【为什么是字符串,额。。。因为你发送的最终都是转换为字节流,至于区分什么数字集合那就用 type
区分就好】
最后这里列举一下响应协议内容:
+
:单行/状态 回复-
:错误回复:
:整数回复$
:批量回复*
:多条批量返回
接着我们来看看各种返回的情况:
单行返回
> SET foo tests
OK
----------
+OK\r\n
复制代码
错误回复
> PUT foo tests
(error) ERR unknown command `PUT`
----------
-ERR unknown command `PUT`
复制代码
整数回复
> EXISTS foo
(integer) 1
----------
:1\r\n
复制代码
批量回复
> GET foo
"0123abcdefghigkl"
----------
$16\r\n0123abcdefghigkl\r\n
> GET foo2
(nil)
----------
$-1\r\n
复制代码
多条批量回复
> LRANGE foo2 0 -1
1) "wxyz"
2) "qrstuv"
3) "lmnop"
------------
*3\r\n$4\r\nwxyz\r\n$6\r\nqrstuv\r\n$5\r\nlmnop\r\n
复制代码
缺点
上述提到的是 5 种编码类型,从数据基本类型上只支持整数和字符串,但是对于其他基本数据类型:浮点数或者是布尔值【目前这两个是用 string/integer
来替换】。缺点还有以下这些:
lrange/zrange
如果内容一样,返回的结果是一致的。但是其实存储的结构是不一样的,返回值对于开发者不明确;- 缺乏重要的基本数据类型;
- 返回的数据格式不是二进制安全的。因为分隔符为
\r\n
,所以错误内容中不能含有这些信息
未完待续。。。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END