10分钟就理解Redis序列化协议,你也能编写redis客户端

前提最近学习Netty的时候想做一个基于redis服务协议的编码解码模块,过程中顺便阅读了Redis服务序列化协议RESP,结合自己的理解对文档进行了翻译并且简单实现了RESP基于JAVA语言的解析 。编写本文的使用使用的JDK版本为[8+] 。

10分钟就理解Redis序列化协议,你也能编写redis客户端

文章插图
 
RESP简介Redis客户端与Redis服务端基于一个称作RESP的协议进行通信,RESP全称为Redis Serialization Protocol,也就是Redis序列化协议 。虽然RESP为Redis设计,但是它也可以应用在其他客户端-服务端(Client-Server)的软件项目中 。RESP在设计的时候折中考虑了如下几点:
  • 易于实现 。
  • 快速解析 。
  • 可读性高 。
RESP可以序列化不同的数据类型,如整型、字符串、数组还有一种特殊的Error类型 。需要执行的Redis命令会封装为类似于字符串数组的请求然后通过Redis客户端发送到Redis服务端 。Redis服务端会基于特定的命令类型选择对应的一种数据类型进行回复(这一句是意译,原文是:Redis replies with a command-specific data type) 。
RESP是二进制安全的(binary-safe),并且在RESP下不需要处理从一个进程传输到另一个进程的批量数据,因为它使用了前缀长度(prefixed-length,后面会分析,就是在每个数据块的前缀已经定义好数据块的个数,类似于Netty里面的定长编码解码)来传输批量数据 。
注意:此处概述的协议仅仅使用在客户端-服务端通信,Redis Cluster使用不同的二进制协议在多个节点之间交换消息(也就是Redis集群中的节点之间并不使用RESP通信) 。
网络层
Redis客户端通过创建一个在6379端口的TCP连接,连接到Redis服务端 。
虽然RESP在底层通信协议技术上是非TCP特定的,但在Redis的上下文中,RESP仅用于TCP连接(或类似的面向流的连接,如Unix套接字) 。
请求-响应模型
Redis服务端接收由不同参数组成的命令,接收到命令并将其处理之后会把回复发送回Redis客户端 。这是最简单的模型,但是有两种例外的情况:
  • Redis支持管道(Pipelining,流水线,多数情况下习惯称为管道)操作 。使用管道的情况下,Redis客户端可以一次发送多个命令,然后等待一次性的回复(文中的回复是replies,理解为Redis服务端会一次性返回一个批量回复结果) 。
  • 当Redis客户端订阅Pub/Sub信道时,该协议会更改语义并成为推送协议(push protocol),也就是说,客户端不再需要发送命令,因为Redis服务端将自动向客户端(订阅了改信道的客户端)发送新消息(这里的意思是:在订阅/发布模式下,消息是由Redis服务端主动推送给订阅了特定信道的Redis客户端) 。
除了上述两个特例之外,Redis协议是一种简单的请求-响应协议 。
RESP支持的数据类型RESP在Redis 1.2中引入,在Redis 2.0,RESP正式成为与Redis服务端通信的标准方案 。也就是如果需要编写Redis客户端,你就必须在客户端中实现此协议 。
RESP本质上是一种序列化协议,它支持的数据类型如下:单行字符串、错误消息、整型数字、定长字符串和RESP数组 。
RESP在Redis中用作请求-响应协议的方式如下:
  • Redis客户端将命令封装为RESP的数组类型(数组元素都是定长字符串类型,注意这一点,很重要)发送到Redis服务器 。
  • Redis服务端根据命令实现选择对应的RESP数据类型之一进行回复 。
在RESP中,数据类型取决于数据报的第一个字节:
  • 单行字符串的第一个字节为+ 。
  • 错误消息的第一个字节为- 。
  • 整型数字的第一个字节为: 。
  • 定长字符串的第一个字节为$ 。
  • RESP数组的第一个字节为* 。
另外,在RESP中可以使用定长字符串或者数组的特殊变体来表示Null值,后面会提及 。在RESP中,协议的不同部分始终以rn(CRLF)终止 。
目前RESP中5种数据类型的小结如下:
数据类型 本文翻译名称 基本特征 例子 Simple String 单行字符串 第一个字节是+,最后两个字节是rn,其他字节是字符串内容 +OKrn Error 错误消息 第一个字节是-,最后两个字节是rn,其他字节是异常消息的文本内容 -ERRrn Integer 整型数字 第一个字节是:,最后两个字节是rn,其他字节是数字的文本内容 :100rn Bulk String 定长字符串 第一个字节是$,紧接着的字节是内容字符串长度rn,最后两个字节是rn,其他字节是字符串内容 $4rndogern Array RESP数组 第一个字节是*,紧接着的字节是元素个数rn,最后两个字节是rn,其他字节是各个元素的内容,每个元素可以是任意一种数据类型 *2rn:100rn$4rndogern 下面的小节是对每种数据类型的更细致的分析 。


推荐阅读