侧边栏壁纸
  • 累计撰写 247 篇文章
  • 累计创建 16 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Redis 客户端与服务端通信协议 RESP 详解

kaixindeken
2021-04-28 / 0 评论 / 0 点赞 / 256 阅读 / 2,166 字

1.jpeg

所谓通信协议指的是通信双方沟通和数据交换的一组约定,在这里,RESP 协议就是 Redis 客户端与服务端沟通和数据交换的约定格式,作为对比,HTTP 协议就是浏览器(Web 客户端)与 Web 服务器进行沟通和数据交换的约定格式,关于网络协议的细节,请参考网络协议部分教程。

RESP 的全称是 REdis Serialization Protocol,即 Redis 序列化协议,这是一个纯文本协议,有人可能质疑文本协议是否浪费流量、牺牲性能,Redis 的作者认为数据库系统的性能瓶颈并不在网络流量,事实也确实如此,所以这里并没有设计为使用二进制协议。

使用纯文本协议的好处官方文档中已经给出:

  • 实现简单
  • 解析快
  • 可读性好

RESP 协议可以序列化多种数据类型,包括整型、字符串、数组,以及错误等。下面我们就来简单介绍下 Redis 客户端和服务端通信过程中如何基于 RESP 协议解析数据。

RESP 协议简介

在 RESP 协议中,数据类型通过它的第一个字节进行判断,然后每部分都是以 \r\n (CRLF) 结尾的。

单行字符串以 + 符号开头:

+hello xueyuanjun\r\n

多行字符串以 $ 符号开头,后跟字符串长度:

$16\r\nhello xueyuanjun\r\n

整数值以 : 符号开头,后跟整数的字符串形式:

:1024\r\n

错误消息以 - 符号开头:

-ERR syntax error\r\n

数组以 * 号开头,后跟数组的长度:

*3\r\n:1\r\n:2\r\n:3\r\n

空字符串通过长度为 0 的多行字符串表示:

$0\r\n\r\n

NULL 则通过长度为 -1 的多行字符串表示:

$-1\r\n

以上就是 RESP 协议的基本约定,接下来就来看看 Redis 请求和响应是如何通过 RESP 协议来表示的。

客户端向服务端发起请求

Redis 客户端向服务端发送的是一组由执行的命令组成的字符串数组,服务端根据不同的命令回复不同类型的数据。

比如一个简单的字符串键值对设置指令 set author kaixindeken,会被序列化成如下 RESP 协议文本传输给 Redis 服务端:

*3\r\n$3\r\nset\r\n$6\r\nauthor\r\n$10\r\nkaixindeken\r\n

可以看到,首先最外层套的是数组一个包含 3 个元素的数组,然后指令的每个部分被拆分为对应的多行字符串元素。

\r\n 会被自动转化为换行符。

服务端返回响应给客户端

前面我们提到 Redis 服务端会根据不同的客户端指令返回不同的响应,比如 set author kaixindeken 指令执行成功后返回的是单行字符串:

+OK\r\n

而如果试图对字符串键值对应的键名进行自增操作,会返回错误信息:

127.0.0.1:6379> set author kaixindeken
OK
127.0.0.1:6379> incr author
(error) ERR value is not an integer or out of range

对应的序列化格式是:

-ERR value is not an integer or out of range\r\n

而如果是整型格式键值,或者不存在的键值对,则可以返回整型的自增结果:

127.0.0.1:6379> incr score
(integer) 1

对应的序列化格式是:

:1\r\n

如果视图获取字符串格式的键值,返回的是多行字符串:

127.0.0.1:6379> get author
"kaixindeken"

对应的序列化格式是:

$10\r\nxueyuanjun\r\n

最后,对于列表、集合、字典类型,返回的通常是数组格式数据:

127.0.0.1:6379> hset post author kaixindeken views 1000
(integer) 2
127.0.0.1:6379> hgetall post
1) "author"
2) "kaixindeken"
3) "views"
4) "1000"

你可以按照 RESP 协议数组、字符串、数字格式组装出对应的序列化格式。

RESP 虽然是为 Redis 通信设计的,但也可以广泛应用于其他客户端与服务端通信场景。

0

评论区