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 }
-
服务端接收数据如下: