【redis知識點整理】 --- RESP協議 + 手寫一個簡單的redis客戶端

RESP協議官網:https://redis.io/topics/protocol
RESP協議中文官網:http://www.redis.cn/topics/protocol.html
本文代碼對應的github地址:https://github.com/nieandsun/redis-study



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!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章