Redis协议,简单实现Jedis客户端
程序员文章站
2022-05-19 14:14:13
...
说明:本人linux的redis设置了密码,所以还是选择了windows的redis,性质都一样
目录
一、Redis协议--RESP
Redis 的客户端和服务端之间采取了一种独立名为 RESP(Redis Serialization Protocol) 的协议,作者主要考虑了以下几个点:
- 容易实现
- 解析快
- 人类可读
注意:RESP 虽然是为 Redis 设计的,但是同样也可以用于其他 C/S 的软件。
二、Redis协议查看及分析
1、写一个假的服务器端来接收Jedis传来的信息,并启动
package com;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @Description
* 假的Redis服务端
* @Author xuexue
* @Date 2019/10/1121:14
*/
public class JedisServer {
public static void main(String[] args) throws IOException {
//默认为本机(127.0.0.1),假的服务端
ServerSocket serverSocket = new ServerSocket(6379);
//接收来自端口6379的信息
Socket accept = serverSocket.accept();
//定义字节数组接收来自Jedis发收过来的信息
byte[] t = new byte[2048];
accept.getInputStream().read(t);
//打印信息
System.out.println(new String(t));
}
}
2、运行Jedis代码
@Test
public void test1() {
//建立连接 需要关闭防火墙 用密码连接
Jedis jedis = new Jedis("127.0.0.1", 6379);
//插入一个字符键age 20
jedis.set("age", "20");
//关闭连接
jedis.close();
}
3、查看结果
4、分析
对指令jedis.set("age", "20")分析,其实就是set(key,value)
*3 | *后面数字表示几组命令,这里三组分别表示set、key、value |
$3 | $后面表示指令的长度,这里SET表示长度为3 |
SET | 表示指令一set |
$3 | $后面表示指令内容的长度,这里key的内容是age,表示长度为3 |
age | 表示指令二key的内容 |
$2 | $后面表示指令内容的长度,这里value的内容是20,表示长度2 |
20 | 表示指令三value的内容 |
这就是RESP协议简单的分析,当然还有很多复杂的,这里就不介绍(特点简单,人类可读)
三、简单手写Jedis客户端
过程
1、手写Jedis客户端set功能(拼接RESP协议,向服务器发送RESP协议,协议内容主要是插入,接收服务器响应信息)
2、手写Jedis客户端get功能(拼接RESP协议,向服务器发送RESP协议,协议内容主要是请求内容,接收服务器返回key的内容)
3、手写Jedis客户端,发送Socket跟服务器通信
直接贴代码,解析很详细
package com;
import java.io.IOException;
import java.net.Socket;
/**
* @Description
* 模拟Jedis,实现字符串set/get方法
* 要点:RESP协议
* @Author xuexue
* @Date 2019/10/11 20:24
*/
public class MyJedisClient {
/**
* 实现Jedis的set方法
* 手写Jedis客户端set功能(拼接RESP协议,向服务器发送RESP协议,协议内容主要是插入,接收服务器响应信息)
* @return String 服务器响应信息
*/
public static String set(Socket socket, String key, String value) throws IOException {
//定义一个变成字符串,用于拼接符合RESP字符串指令
StringBuffer stf = new StringBuffer();
//拼接指令长度SET(key,value)三个指令,长度为3,就是*3
stf.append("*3").append("\r\n");
//拼接指令SET字符串,拼接SET指令长度为$3
stf.append("$3").append("\r\n");
stf.append("SET").append("\r\n");
//拼接key指令内容长度$key.length(),拼接指令key字符串,
stf.append("$").append(key.length()).append("\r\n");
stf.append(key).append("\r\n");
//拼接指令value.getBytes()字符串,拼接key指令内容长度$key.length()
stf.append("$").append(value.length()).append("\r\n");
stf.append(value).append("\r\n");
byte[] b = new byte[2048];
socket.getOutputStream().write(stf.toString().getBytes());
socket.getInputStream().read(b);
return new String(b);
}
/**
* 实现Jedis的get方法
* 手写Jedis客户端get功能
* (拼接RESP协议,向服务器发送RESP协议,协议内容主要是请求内容,接收服务器返回内容)
* @return String 服务器返回key的内容
*/
public static String get(Socket socket, String key) throws IOException {
//定义一个变成字符串,用于拼接符合RESP字符串指令
StringBuffer stf = new StringBuffer();
//拼接指令长度SET(key,value)三个指令,长度为3,就是*3
stf.append("*2").append("\r\n");
//拼接指令SET字符串,拼接SET指令长度为$3
stf.append("$3").append("\r\n");
stf.append("GET").append("\r\n");
//拼接key指令内容长度$key.length(),拼接指令key字符串,
stf.append("$").append(key.length()).append("\r\n");
stf.append(key).append("\r\n");
byte[] b = new byte[2048];
socket.getOutputStream().write(stf.toString().getBytes());
socket.getInputStream().read(b);
return new String(b);
}
public static void main(String[] args) throws IOException {
//手写Jedis客户端,发送Socket跟服务器通信
Socket socket = new Socket("127.0.0.1",6379);
String lisi = MyJedisClient.set(socket, "lisi", "333");
System.out.println(lisi);
System.out.println(MyJedisClient.get(socket,"lisi"));
}
}
打开windows的redis
运行代码
运行windowsRedis客户端,检查是否插入