RESP协议官网:https://redis.io/topics/protocol
RESP协议中文官网:http://www.redis.cn/topics/protocol.html
本文代码对应的github地址:https://github.com/nieandsun/redis-study
文章目录
- 1 RESP协议简介
- 2 自己手写一个简单的redis客户端
1 RESP协议简介
RESP( REdis Serialization Protocol) 是Redis客户端与Redis服务器间进行通讯的协议。其主要特点如下:
- 容易实现
- 解析快
- 人类可读
RESP 底层采用的是 TCP 的连接方式, 通过 tcp 进行数据传输, 然后根据解析规则解析相应信息, 完成交互。
我们可以测试下, 首先运行一个 serverSocket 监听 6379, 来接收 redis 客户端的请求信息, 实现如下:
//模拟redis服务器
public class ServerRedis {
public static void main(String[] args) {
try {
//监听6379端口
ServerSocket serverSocket = new ServerSocket(6379);
Socket rec = serverSocket.accept();
byte[] result = new byte[2048];
rec.getInputStream().read(result);
System.out.println(new String(result));
} catch (IOException e) {
e.printStackTrace();
}
}
}
再通过redis的客户端jedis给6379端口发送请求:
public class ClientRedis {
/***
* 使用redis客户端jedis给6379端口发送消息
* @param args
*/
public static void main(String[] args) {
Jedis jedis = new Jedis("127.0.0.1", 6379);
jedis.set("name", "lisonLength");
jedis.close();
}
}
测试发现,服务端打印的信息如下:
这就是Resp协议的结构 — 》 AOF存储的就是这些命令,有兴趣的可以回看一下我的文章《【redis知识点整理】 — Redis的持久化》。
2 自己手写一个简单的redis客户端
1中可以看到,其实Jedis就是将我们的key 和 Value拼装成满足RESP协议的字符串通过Socket发送给了Redis服务器来完成与Redis服务器的交互。
这时候我们肯定会想,假如我们自己按照RESP的规范,拼装一个字符串,然后通过Socket发送给redis服务器,能不能完成存储和查询呢???
其实是可以的,举例如下:
package com.nrsc.redis.learning.resp;
import java.io.IOException;
import java.net.Socket;
public class SelfRedisClient {
/*
*3
$3
SET
$4
name
$6
rehash
*/
public static String set(Socket socket, String key, String value) throws IOException {
//按照RESP协议拼接字符串
StringBuffer str = new StringBuffer();
str.append("*3").append("\r\n");
str.append("$3").append("\r\n");
str.append("SET").append("\r\n");
str.append("$").append(key.getBytes().length).append("\r\n");
str.append(key).append("\r\n");
str.append("$").append(value.getBytes().length).append("\r\n");
str.append(value).append("\r\n");
socket.getOutputStream().write(str.toString().getBytes());
byte[] response = new byte[2048];
socket.getInputStream().read(response);
return new String(response);
}
/*
*2
$3
GET
$4
name
*/
public static String get(Socket socket, String key) throws IOException {
//按照RESP协议拼接字符串
StringBuffer str = new StringBuffer();
str.append("*2").append("\r\n");
str.append("$3").append("\r\n");
str.append("GET").append("\r\n");
str.append("$").append(key.getBytes().length).append("\r\n");
str.append(key).append("\r\n");
socket.getOutputStream().write(str.toString().getBytes());
byte[] response = new byte[2048];
socket.getInputStream().read(response);
return new String(response);
}
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1", 6379);
String set = set(socket, "shaka", "loveStus");
System.out.println(set);
System.out.println(get(socket, "shaka"));
}
}
测试结果如下,可以看到用我们自己写的客户端确实可以与redis服务器进行交互,完成存储和读取数据。
end!!!