說明:本人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客戶端,檢查是否插入