Redis C/S 间数据交互「一」|小册免费学

本篇文章针对的是 redis RESP2 协议分析

整体分析

从整体角度来看,redis 客户端和服务端交互其实就两个:

  • 客户端发送:
    • 命令
    • 缓存键,缓存值
  • 服务端发送:
    • 返回给客户端的结果
    • 获取成功的 OK 标志「字符串」
    • 成功写入的元素个数
    • 错误信息「ERR

从整体来讲,交互内容分为以下几个点:

  1. 命令:Set, Get
  2. 缓存键:Set key value 中的 key ,只能是字符串;
  3. 缓存单个值:Set key value 中的 value 。字符串,数字,一般是这些;
  4. 缓存集合:HSet key value1 value2。缓存多个值的时候,传输的可能是不同类型的值;
  5. OK:命令执行成功,返回一个 OK 回复;
  6. Int:写入N个元素成功,返回 N 对应的int值
  7. ERR:错误信息

上面是命令的形式,下面我们讨论一下交互的数据:

首先 RESP 底层走的是 TCP ,最需要的考虑的问题之一就是粘包拆包,那么 redis server 如何区分出正确的包呢?通常3种方法:

  1. 数据包固定长度,不足不全,超过截断
  2. 分隔符区分,HTTP 就是用换行符区分的
  3. 数据包头部设置数据长度

自定义协议

redis 采取的是自定义协议格式区分不同命令请求,举个例子:

SET key value

=> 

*3\r\n$3\r\nSET\r\n$9\r\nkey\r\n$6\r\nvalue\r\n
复制代码

一时间看不懂这是啥,区分解释一下:

  1. \r\n:分隔符
  2. *3:命令有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
喜欢就支持一下吧
点赞0 分享