Redis6通信协议升级为RESP3,一口气读取了13种新的数据类型。RedisSerializationProtocol,基于这个实现简单、解析性能优异的通信协议,Redis服务器端和客户端可以通过底层命令进行数据通信。随着Redis版本的不断更新和功能的迭代,RESPV2协议逐渐不能满足新的需求。为了适应Redis6.0出现的一些新功能,在其基础上开发了新的下一代RESP3协议。.我们先回顾一下继承自RESPV2的五种数据返回类型。了解了这些类型的局限性之后,我们再来看看RESP3中新的数据返回类型在哪些方面做了改进。1、继承RESPv2的类型首先,协议中数据的请求格式与RESPv2完全一致。请求格式如下:*<参数个数>CRLF$<参数1的字节长度>CRLF<参数1的数据>CRLF$<参数2的字节长度>CRLF<参数2的数据>CRLF...$<参数N的字节长度>CRLF<参数N的数据>CRLF每行末尾的CRLF转换成程序语言是\r\n,即回车换行。以命令集名称hydra为例,转换过程及转换结果如下:了解发送协议后,针对不同类型的回复进行如下测试。如何模拟这个过程?在上一篇文章中,我们通过java代码中的Socket连接redis服务,发送数据,接收返回结果,模拟了这个协议。不过我们今天采用更简单的方法,直接在命令行下使用telnet连接即可。以我本机启动的redis为例,直接输入telnet127.0.0.16379连接redis服务。之后,将包含换行符的命令一次性复制到命令行中,然后回车即可收到Redis服务的回复:来看看继承自RESPV2的五种返回格式。为了统一命名规范,引入RESP3官方文档中的新名称来替代RESPV2中的旧名称。例如,不再使用批回复和多批回复的旧名称。Simplestring表示简单字符串回复,只有一行回复,回复内容以+开头,不允许换行,以\r\n结尾。有很多命令在成功执行后只会回复OK。使用这种格式,可以有效地减少传输和分析的开销。仍以上面的set命令为例,发送请求:*3$3set$4name$5hydra收到回复:+OK\r\nSimpleerror错误回复,可以看成是简单字符串回复的变体形式,它们之间的格式也很相似,唯一的区别是第一个字符以-开头,错误回复的内容通常是错误类型和描述错误的字符串。错误回复出现在一些异常场景中,比如发送了一条错误指令,操作数个数错误,就会进行错误回复。发送错误命令:*1$8Dr.Hydra收到回复,提示错误信息:https://mp.weixin.qq.com/s/rLk2EW0TKAIkQvx1WefafA#:~:text=%2DERR%C2%A0unknown%C2%A0command%C2%A0%60Dr.Hydra%60%2C%C2%A0with%C2%A0args%C2%A0beginning%C2%A0with%3A%5Cr%5CnNumber整数回复,也被广泛使用,以:开头,结尾与\r\n,用于返回一个整数。比如执行incr返回自增值,执行llen返回数组长度,或者用exists命令返回的0或者1作为判断key是否存在的依据,所有的这些使用整数回复。发送命令查看数组长度:*2$4llen$7myarray收到回复::4\r\nBlobstring多行字符串的回复也称为批量回复,在RESPV2。它以$开头,后面是要发送的字节长度,然后是\r\n,然后发送实际数据,最后以\r\n结束。如果要回复的数据不存在,则回复长度为-1。发送get命令请求:*2$3get$4name收到回复:$5\r\nhydra\r\nArray在RESPV2中可以理解为多批次回复。当服务器要返回多个值时,例如返回一些Array,当使用元素集合时。它以*开头,后面是返回元素的个数,后面是上面的多个BlobString。*4$6lrange$7myarray$10$2-1收到回复,其中包含集合中的4个元素:*4$11$12$12$232RESPV2协议继承的5种返回数据类型的简单回顾到此结束,我们开始吧RESP3协议新特性的探索之旅。2、RESP3中的新类型目前在Redis6.0.X版本,仍然是默认使用的RESPV2协议,在兼容RESPV2的基础上,还支持启用RESP3。预计在未来的某个版本中,Redis可能会全面切换到RESP3,但这样做会对目前的Redis客户端连接工具产生相当大的影响,底层通信需要根据协议内容进行修改。使用telnet连接redis服务后,首先输入如下命令切换到RESP3版本的协议。至于具体的返回数据以及hello命令的数据表示的含义,这里先略过,以后再看。hello3下面我们来详细了解一下RESP3,除了保留上面5种老的回复类型外,还新增了13种通信返回数据类型,部分数据类型会通过实例进行演示。为了看起来更简洁,以下演示示例使用原始命令发送命令,不再转换为协议格式,并在数据返回结果中省略每行末尾的\r\n!(1)Null新协议使用下划线字符后跟CR和LF字符来表示空值,即用_\r\n代替原来的单个空值返回$-1。例如使用get命令查找不存在的key时:gethydraRESPV2返回:$-1RESP3返回:_(2)双浮点数返回时以逗号开头,格式为,\r\n,使用zsetscorekeymember获取Score命令进行测试:zscorefruitappleRESPV2使用BulkString格式返回:$185.6600000000000001RESP3返回格式:,5.6600000000000001(3)布尔数据返回值,其中true表示为#t\r\n,而false表示为#f\r\n。但是Hydra暂时没有找到返回boolean类型结果的例子,即使lua脚本直接返回boolean类型也无法实现。eval"returntrue"0eval"returnfalse"0上面lua脚本返回true时结果为:1\r\n,返回false时结果为_\r\n,这是因为lua中boolean类型为true将在redis中转为整型返回1,false类型会转为NilBulk。至于哪些指令可以返回布尔数据,有知道的朋友可以给我留言补充。(4)Blob错误类似于字符串类型,其格式为!\r\n\r\n,但与简单错误类型相同,使用!\r\n\r\n。在开头表示返回错误信息描述。例如会返回错误SYNTAXinvalidsyntax,格式如下:!21SYNTAXinvalidsyntax(5)VerbatimstringVerbatimstring也表示一种字符串格式,和BlobString很相似,只是用=来代替开头的$,而后面的三个字节提供了字符串格式的信息,比如txt表示纯文本,mkd表示markdown格式,第四个字节固定为:.这种格式适合在没有任何转义或过滤的情况下显示给用户。使用延迟事件统计和分析命令进行测试,发送:latencydoctorRESP2返回数据或BlobString格式:$196Dave,在这个Redis实例的生命周期内没有观察到延迟尖峰,没有丝毫。老实说,我认为你应该冷静地坐下来,吃一颗减压药,好好想想。RESPV3返回的数据采用了一种新格式:=200txt:Dave,在这个Redis实例的生命周期内没有观察到延迟峰值,丝毫没有。老实说,我认为你应该冷静地坐下来,吃一颗减压药,好好想想。(6)BignumberBignumber类型用于返回非常大的整数,可以表示有符号64位数字范围内的整数,包括正数或负数,但注意不要包含小数。数据格式为(\r\n,以左括号开头。示例如下:(3492890328409238509324850943850943825024385注意,当大数不可用时,客户端会返回一串数据。(7)聚合数据类型为和我们前面介绍的一样,聚合数据类型可以理解为聚合数据类型,不同于给定数据类型的单个值,这也是RESP3的一个核心思想,需要能够从协议和类型的角度来描述具有不同语义的聚合数据类型。聚合数据类型的格式如下,通常由聚合类型、元素个数、具体单个元素组成:
