1.Redis网络通信协议

Redis底层网络通信协议其实是通过TCP来完成的。

2.Redis通信协议

Redis的通信协议首先是以行来划分,每行以\r\n行结束。每一行都有一个消息头,消息头共分为5种分别如下:
(+) 表示一个正确的状态信息,具体信息是当前行+后面的字符。
(-) 表示一个错误信息,具体信息是当前行-后面的字符。
(*) 表示消息体总共有多少行,不包括当前行,*后面是具体的行数。
()表示下一行数据长度,不包括换行符长度\r\n,)表示下一行数据长度,不包括换行符长度\r\n,后面则是对应的长度的数据。
( : ) 表示返回一个数值,:后面是相应的数字节符。
举个例子:

set demo 123456

*3\r\n          #消息一共有三行
$3\r\n          #第一行有字节数为3
set\r\n         #第一行的消息
$4\r\n          #第二行字节数为4 
demo\r\n        #第二行的消息
$6\r\n          #第三行字节数为6
123456\r\n      #第三行的消息
+OK\r\n         #操作成功

3.Redis通信协议实现

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 demo 123456\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 demo\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 demo” , 这种只是"内联命令", 而不是Redis真正的通信协议.

  • 问: 什么意思呢? 答: 就是说你可以像之前那样给服务端发, 服务器端接受到后, 会遍历一遍你发送的内容, 最后根据空格来分析你所发的内容的含义.
  • 问: 这样有什么不好的吗? 答: 如果这样的话, 你就把解析的工作交给了服务器来做, 会加大服务器的工作量.
  • 问: 那怎么样才是符合规范的呢? 符合协议的话真的会提高服务器的效率? 答: 首先看一下符合协议的客户端和服务端之间的交互把
    例: set java python ,抓到包之后是这样的:

红色是客户端发送的内容, 蓝色是服务器端返回的内容.

咱们一起解析一下:

*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) )

4 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