网络协议之:redis protocol 详解

目录

  • 简介
  • redis的高级用法
    • Redis中的pipline
    • Redis中的Pub/Sub
  • RESP protocol
    • Simple Strings
    • Bulk Strings
    • RESP Integers
    • RESP Arrays
    • RESP Errors
  • Inline commands
  • 总结
简介redis是一个非常优秀的软件,它可以用作内存数据库或者缓存 。因为他的优秀性能,redis被应用在很多场合中 。
redis是一个客户端和服务器端的模式,客户端和服务器端是通过TCP协议进行连接的 , 客户端将请求数据发送到服务器端,服务器端将请求返回给客户端 。这样一个请求流程就完成了 。
当然在最开始的时候,因为用的人很少,系统还不够稳定,通过TCP协议传输的数据不规范的 。但是当用的人越来越多,尤其是希望开发适用于不同语言和平台的redis客户端的时候,就要考虑到兼容性的问题了 。
这时候客户端和服务器端就需要一个统一的交互协议,对于redis来说这个通用的交互协议就叫做Redis serialization protocol(RESP) 。
RESP是在Redis 1.2版本中引入的,并在Redis 2.0中成为了与 Redis 服务器通信的标准方式 。
这就是说,从Redis 2.0之后,就可以基于redis protocol协议开发出自己的redis客户端了 。
redis的高级用法一般来说,redis的客户端和服务器端组成的是一个请求-响应的模式,也就是说客户端向服务器端发送请求,然后得到服务器端的响应结果 。
请求和响应是redis中最简单的用法 。熟悉redis的朋友可能会想到了两个redis的高级用法,这两个用法并不是传统意义上的请求-响应模式 。
到底是哪两种用法呢?
第一种就是redis支持pipline,也就是管道操作,管道的好处就是redis客户端可以一次性向服务器端发送多条命令,然后等待服务器端的返回 。
第二种redis还支持Pub/Sub,也就是广播模型,在这一种情况下,就不是请求和响应的模式了,在Pub/Sub下,切换成了服务器端推送的模式 。
Redis中的pipline为什么要用pipline呢?
因为redis是一个典型的请求响应模式,我们来举个常见的incr命令的例子:
Client: INCR XServer: 1Client: INCR XServer: 2Client: INCR XServer: 3Client: INCR XServer: 4
事实上客户端只想得到最终的结果,但是每次客户端都需要等待服务器端返回结果之后,才能发送下一次的命令 。这样就会导致一个叫做RTT(Round Trip Time)的时间浪费 。
虽然每次RTT的时间不长,但是累计起来也是一个非常客观的数字 。
那么可不可以将所有的客户端命令放在一起发送给服务器呢? 这个优化就叫做Pipeline 。
piepline的意思就是客户端可以在没有收到服务器端返回的时候继续向服务器端发送命令 。
上面的命令可以用pipline进行如下改写:
(printf "INCR X\r\nINCR X\r\nINCR X\r\nINCR X\r\n"; sleep 1) | nc localhost 6379:1:2:3:4因为redis服务器支持TCP协议进行连接,所以我们可以直接用nc连到redis服务器中执行命令 。
在使用pipline的时候有一点要注意,因为redis服务器会将请求的结果缓存在服务器端 , 等到pipline中的所有命令都执行完毕之后再统一返回,所以如果服务器端返回的数据比较多的情况下,需要考虑内存占用的问题 。
那么pipline仅仅是为了减少RTT吗?
熟悉操作系统的朋友可能有听说过用户空间和操作系统空间的概念,从用户输入读取数据然后再写入到系统空间中,这里涉及到了一个用户空间的切换 , 在IO操作中 , 这种空间切换或者拷贝是比较耗时的 , 如果频繁的进行请求和响应,就会造成这种频繁的空间切换,从而降低了系统的效率 。
使用pipline可以一次性发送多条指令,从而有效避免空间的切换行为 。
Redis中的Pub/Sub和Pub/Sub相关的命令是SUBSCRIBE, UNSUBSCRIBE 和 PUBLISH 。
为什么要用Pub/Sub呢?其主要的目的就是解耦,在Pub/Sub中消息发送方不需要知道具体的接收方的地址,同样的对于消息接收方来说 , 也不需要知道具体的消息发送方的地址 。他们只需要知道关联的主题即可 。
subscribe和publish的命令比较简单,我们举一个例子,首先是客户端subscribe topic:
redis-cli -h 127.0.0.1127.0.0.1:6379> subscribe topicReading messages... (press Ctrl-C to quit)1) "subscribe"2) "topic"3) (integer) 1然后在另外一个终端,调用publish命令:
redis-cli -h 127.0.0.1127.0.0.1:6379> publish topic "what is your name?"(integer) 1可以看到客户端会收到下面的消息:
1) "message"2) "topic"3) "what is your name?"

推荐阅读