H__D  

  Redis的通信协议是什么。就是客户端与服务端按照双方约定的规则来进行的编码方式,客户端将要发送的命令进行编码,然后服务端收到后,使用同样的协议进行解码,服务端处理完成后,再次编码返回给客户端,客户端解码拿到返回结果,这样就完成了一次通信。

  官网文档:https://redis.io/topics/protocol

一、Redis协议规范

  Redis客户端使用称为RESP(Redis序列化协议)的协议与Redis服务器进行通信虽然该协议是专为Redis设计的,但它可以用于其他客户端-服务器软件项目。

  RESP是以下方面的折衷方案:

  • 易于实现。
  • 快速解析。
  • 可读性强。

  RESP可以序列化不同的数据类型,例如整数,字符串,数组。还有一种特定的错误类型。请求以字符串数组的形式从客户端发送到Redis服务器,这些字符串表示要执行的命令的参数。Redis使用特定于命令的数据类型进行回复。

  RESP是二进制安全的,并且不需要处理从一个进程传输到另一个进程的批量数据,因为它使用前缀长度来传输批量数据。

  注意:此处概述的协议仅用于客户端-服务器通信。Redis Cluster使用不同的二进制协议以在节点之间交换消息。

二、网络层

客户端连接到Redis服务器,以创建与端口6379的TCP连接。

尽管RESP在技术上不是特定于TCP的,但在Redis的上下文中,该协议仅与TCP连接(或等效的面向流的连接,如Unix套接字)一起使用。

三、请求-响应模型

Redis接受由不同参数组成的命令。收到命令后,将对其进行处理并将答复发送回客户端。

这是最简单的模型,但是有两个例外:

  • Redis支持流水线化(在本文档的后面部分有介绍)。因此,客户端可以一次发送多个命令,并在以后等待答复。
  • 当Redis客户端订阅Pub / Sub通道时,该协议会更改语义并成为推送协议,也就是说,客户端不再需要发送命令,因为服务器将自动向客户端发送新消息(对于客户端的通道被订阅)。

除了上述两个例外,Redis协议是一种简单的请求-响应协议。

四、RESP协议说明

RESP协议是在Redis 1.2中引入的,但是它成为Redis 2.0中与Redis服务器通信的标准方法。这是您应该在Redis客户端中实现的协议。

RESP实际上是一种序列化协议,支持以下数据类型:简单字符串,错误,整数,批量字符串和数组。

在Redis中将RESP用作请求-响应协议的方式如下:

  • 客户端将命令作为RESP大容量字符串数组发送到Redis服务器。
  • 服务器根据命令实现以RESP类型之一进行回复。

在RESP中,某些数据的类型取决于第一个字节:

  • 对于简单字符串,回复的第一个字节为“ +”
  • 对于错误,回复的第一个字节为“-”
  • 对于整数,回复的第一个字节为“:”
  • 对于散装字符串,回复的第一个字节为“ $”
  • 对于数组,回复的第一个字节为“ *

另外,RESP能够使用Bulk Strings或Array的特殊变体来表示Null值,如稍后指定。

在RESP中,协议的不同部分始终以“ \ r \ n”(CRLF)终止。

五、RESP验证

  Redis客户端与server端通信,本身就是基于tcp的一个Request/Response模式。并且jedis与redis底层通信基于socket(可以查看jedis的set方法源码可知),是遵循resp通信协议。

  实验:通过ServerSocket模拟redis服务端,使用jedis向ServerSocket发送数据 

  代码需要引入jedis依赖 

  •  ServerSocket模拟redis服务端代码
    1 @Test
    2 public void server() throws IOException {
    3     ServerSocket serverSocket = new ServerSocket(6379);
    4     Socket socket = serverSocket.accept();
    5     byte[] bytes = new byte[1024];
    6     int len = socket.getInputStream().read(bytes);
    7     System.out.println(new String(bytes, 0, len));
    8 }
  • jedis向ServerSocket发送数据代码

    1 @Test
    2 public void client() {
    3     Jedis jedis = new Jedis("127.0.0.1", 6379);
    4     String ret = jedis.set("aaa", "11");
    5 }
  • 服务端接收数据如下:

   

posted on 2021-05-15 18:45  H__D  阅读(866)  评论(0编辑  收藏  举报