前提最近学习Netty的时候想做一个基于redis服务协议的编码解码模块,过程中顺便阅读了Redis服务序列化协议RESP,结合自己的理解对文档进行了翻译并且简单实现了RESP基于JAVA语言的解析 。编写本文的使用使用的JDK版本为[8+] 。
文章插图
RESP简介Redis客户端与Redis服务端基于一个称作RESP的协议进行通信,RESP全称为Redis Serialization Protocol,也就是Redis序列化协议 。虽然RESP为Redis设计,但是它也可以应用在其他客户端-服务端(Client-Server)的软件项目中 。RESP在设计的时候折中考虑了如下几点:
- 易于实现 。
- 快速解析 。
- 可读性高 。
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客户端) 。
RESP支持的数据类型RESP在Redis 1.2中引入,在Redis 2.0,RESP正式成为与Redis服务端通信的标准方案 。也就是如果需要编写Redis客户端,你就必须在客户端中实现此协议 。
RESP本质上是一种序列化协议,它支持的数据类型如下:单行字符串、错误消息、整型数字、定长字符串和RESP数组 。
RESP在Redis中用作请求-响应协议的方式如下:
- Redis客户端将命令封装为RESP的数组类型(数组元素都是定长字符串类型,注意这一点,很重要)发送到Redis服务器 。
- Redis服务端根据命令实现选择对应的RESP数据类型之一进行回复 。
- 单行字符串的第一个字节为+ 。
- 错误消息的第一个字节为- 。
- 整型数字的第一个字节为: 。
- 定长字符串的第一个字节为$ 。
- RESP数组的第一个字节为* 。
目前RESP中5种数据类型的小结如下:
数据类型 本文翻译名称 基本特征 例子 Simple String 单行字符串 第一个字节是+,最后两个字节是rn,其他字节是字符串内容 +OKrn Error 错误消息 第一个字节是-,最后两个字节是rn,其他字节是异常消息的文本内容 -ERRrn Integer 整型数字 第一个字节是:,最后两个字节是rn,其他字节是数字的文本内容 :100rn Bulk String 定长字符串 第一个字节是$,紧接着的字节是内容字符串长度rn,最后两个字节是rn,其他字节是字符串内容 $4rndogern Array RESP数组 第一个字节是*,紧接着的字节是元素个数rn,最后两个字节是rn,其他字节是各个元素的内容,每个元素可以是任意一种数据类型 *2rn:100rn$4rndogern 下面的小节是对每种数据类型的更细致的分析 。
推荐阅读
- 番荔枝释迦有什么区别
- 看完这些“秋天的第一杯奶茶”,手里的蜜雪冰城忽然就不香了!
- 茶就是幸福
- 蓝翔技校校长跨省打架 蓝翔技校跨省打架
- 汽车加油不是加满就是加200?学习起来,别再加错了
- 大盘、消费、医药、半导体科技板块全线大跌,有闲钱就加点仓吧!
- 阳气不到的地方就会生病
- 5种日用品该扔就扔,当心毁了健康!
- 一什么相声? 相声就是要逗乐能把观众逗乐的就是好的相声
- 选择安溪读茶校 升学就业两不愁