中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

redis通信協議protocol介紹

發布時間:2020-05-22 15:59:45 來源:億速云 閱讀:236 作者:鴿子 欄目:關系型數據庫

redis的ping pong

登錄redis cli客戶端后, 輸入ping, 服務器會返回pong, 來表示連接狀況是完好的, 也表示了服務器大體上是正常運轉的.

redis通信協議protocol介紹

其中的第一行是我用docker 啟動的客戶端, 大家如果不是docker的話, 自己正常啟動redis -cli就行..

ping之后就會收到pong

使用Java socket 來實現 Redis 的ping pong

public static void main(String[] args) throws Exception {
        // socket
        Socket socket = new Socket("140.143.135.210", 6379);
 
        // oi流
        OutputStream os = socket.getOutputStream();
        InputStream is = socket.getInputStream();
 
        // 向redis服務器寫
        os.write("PING\r\n".getBytes());
 
        //從redis服務器讀,到bytes中
        byte[] bytes = new byte[1024];
        int len = is.read(bytes);
 
        // to string 輸出一下
        System.out.println(new String(bytes,0,len));
    }

為什么會有一個 '+'符號 呢?  redis -cli里是沒有這個加號的呀?

這個和通信協議有關, 一會兒再介紹具體的含義. 不過redis -cli只是把這個'+'符號吞掉處理了, 沒顯示出來罷了。

public static void main(String[] args) throws Exception {
        // socket
        Socket socket = new Socket("140.143.135.210", 6379);
 
        // oi流
        OutputStream os = socket.getOutputStream();
        InputStream is = socket.getInputStream();
 
        // 向redis服務器寫
        os.write("PING\r\n".getBytes());
 
        //從redis服務器讀,到bytes中
        byte[] bytes = new byte[1024];
        if(is.read()=='+'){
            // to string 輸出一下
            int len = is.read(bytes);
            System.out.println(new String(bytes,0,len));
        }
        // else if $
        // else if *
        // else
    }

實現SET 和 GET

set:

public static void main(String[] args) throws Exception {
        // socket
        Socket socket = new Socket("140.143.135.210", 6379);
 
        // oi流
        OutputStream os = socket.getOutputStream();
        InputStream is = socket.getInputStream();
 
        // 向redis服務器寫
        os.write("set hello world123\r\n".getBytes());
 
        //從redis服務器讀,到bytes中
        byte[] bytes = new byte[1024];
        int len = is.read(bytes);
 
        // to string 輸出一下
        System.out.println(new String(bytes,0,len));
    }

get:

public static void main(String[] args) throws Exception {
        // socket
        Socket socket = new Socket("140.143.135.310", 6379);
 
        // oi流
        OutputStream os = socket.getOutputStream();
        InputStream is = socket.getInputStream();
 
        // 向redis服務器寫
        os.write("get hello\r\n".getBytes());
 
        //從redis服務器讀,到bytes中
        byte[] bytes = new byte[1024];
        int len = is.read(bytes);
 
        // to string 輸出一下
        System.out.println(new String(bytes,0,len));
    }解釋上面例子中的+和$符號

加號'+' 是來表示狀態回復的, 在redis服務端向客戶端返回狀態信息時, 就會先發送一個`+`符號來開頭.

接下來是相應的狀態信息, 例如'OK'什么的.

最后, 要以'\r\n' 來結尾... 咱們看一下代碼就明白了

public static void main(String[] args) throws Exception {
        // socket
        Socket socket = new Socket("140.143.135.210", 6379);
 
        // oi流
        OutputStream os = socket.getOutputStream();
        InputStream is = socket.getInputStream();
 
        // 向redis服務器寫
        os.write("set hello world123\r\n".getBytes());
 
        //從redis服務器讀,到bytes中
        byte[] bytes = new byte[1024];
        if (is.read() == '+') {
            System.out.println("這是一個狀態回復哦! 怎么知道的呢? `+` 號就表示 '狀態回復' 了");
            int len = is.read(bytes);
            System.out.println("回復的狀態是: " + new String(bytes, 0, len));
        }
 
        // 大家想不想看看bytes里面到底有幾個字符嗎?
        System.out.println(Arrays.toString(bytes));
        // 輸出的是 [79, 75, 13, 10, 0, 0, 0, 0, 0,....]
        // 其中 79 75 是 `OK`
        // 其中 13 10 是 `\r\n`
        // 后面的一串0 是 表示沒有后續內容, 已經讀完.
    }

$ 表示批量讀取, 一般格式是: $<數字>, 數字來表示正文的內容的字節數

redis通信協議protocol介紹

抓包后是這樣的, 客戶端向服務端發送了"get hello", 服務端向客戶端發送了藍色的這兩行.

public static void main(String[] args) throws Exception {
        // socket
        Socket socket = new Socket("140.143.135.210", 6379);
 
        // oi流
        OutputStream os = socket.getOutputStream();
        // 為了解析'\r\n'方便, 我就用改為字符流了
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
 
        // 向redis服務器寫
        os.write("get hello\r\n".getBytes());
 
        // 緩沖數組
        char[] chars = new char[1024];
 
        //從redis服務器讀,到bytes中
        if (br.read() == '$') {
            System.out.println("這是一個批量回復哦! 怎么知道的呢? `$` 號就表示 '批量回復' 了");
            System.out.println("$ 后面會跟一個數字, 來表示正文內容的大小");
            // readLine直接能判斷'\r' '\n'
            int len = Integer.parseInt(br.readLine());
            System.out.println("$后面跟著的數字是: " + len + ", 表示正文是" + len + "個字節, 接下來只要讀取" + len + "個字節就好了");
 
            // 接下來只讀取len個字符就ok了  (其實單位應該是字節, 但是我中途為了readLine省事, 改用了字符流, 個數是不變的)
            br.read(chars, 0, len);
            System.out.println("get到的結果是: " + new String(chars, 0, len) + ", 數一數真的是" + len + "個字符");
        }
    }

Redis通信協議就只是這樣?

no!!!剛才客戶端向服務端發送的 "get hello" , 這種只是"內聯命令", 而不是Redis真正的通信協議.

問: 什么意思呢? 答:  就是說你可以像之前那樣給服務端發, 服務器端接受到后, 會遍歷一遍你發送的內容, 最后根據空格來分析你所發的內容的含義.

問: 這樣有什么不好的嗎?  答: 如果這樣的話, 你就把解析的工作交給了服務器來做, 會加大服務器的工作量.

問: 那怎么樣才是符合規范的呢? 符合協議的話真的會提高服務器的效率? 答: 首先看一下符合協議的客戶端和服務端之間的交互把.如下例子:

例: set java python ,抓到包之后是這樣的:

redis通信協議protocol介紹

紅色是客戶端發送的內容, 藍色是服務器端返回的內容.

咱們一起解析一下:

*3表示 , 客戶端即將發送3段內容

哪三段呢? 第一段: '$3 SET'  第二段: '$4 java'   第三段: '$6 python'

更嚴格地說: 第一段: '$3\r\nSET\r\n'  第二段:'$4\r\njava\r\n'  第三段:'$6\r\npython\r\n'

$符號的意思在上一小節就已經提到過了, 表示下文的內容的長度, 方便服務器進行讀取.

例如: $6就已經把python的長度給匯報出來了, 服務器只需要截取區間[index, index+6]就好了, 不需要去找空格在什么地方(找空格的時間復雜度是O(n), 而$6這種寫法是O(1) )

Jedis

其實Jedis做的工作大體就是把SET key value 這樣的格式轉化為下面這種格式, 然后發到Redis服務端:

*3\r\n
$3\r\n
SET\r\n
$3\r\n
key\r\n
$5\r\n
value\r\n

以上就是redis通信協議(protocol)的詳細內容,更多請關注億速云其它相關文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

体育| 慈利县| 神池县| 高邑县| 阳高县| 闵行区| 图木舒克市| 三河市| 宜宾市| 平南县| 寿光市| 于都县| 阿图什市| 萍乡市| 合山市| 安国市| 肇州县| 砚山县| 新绛县| 大田县| 五指山市| 油尖旺区| 喀什市| 南郑县| 兴仁县| 平凉市| 雷州市| 临高县| 漳平市| 翼城县| 福海县| 隆子县| 民县| 吉木萨尔县| 合水县| 泸溪县| 兴安盟| 桓仁| 南平市| 仁怀市| 邳州市|