概述
redis 客戶端與服務端通信的本質就是基於 socket 的網絡編程, 通過字節流來傳輸數據, 在將數據轉成字節流之前, 客戶端需要將待傳輸的數據按照具體的通信協議格式組裝一下, 本文主要來分析的是 redis 客戶端是通過什麼樣的數據格式從服務端 讀寫數據 的.
插入一條數據
如果往 redis 中插入一條 key=username, value=zhangsan
的數據, 命令如下:
SET USERNAME ZHANGSAN
實際的通信數據(轉爲字節之前), 如下所示:
// 原始字符串
*3\r\n$3\r\nSET\r\n$8 \r\nUSERNAME\r\n$8\r\nZHANGSAN
// 爲了方便, 格式化如下
*3
$3
SET
$8
USERNAME
$8
ZHANGSAN
協議格式說明
-
爲了形象表示, redis 客戶端傳輸的數據格式由 N 多個 段 組成, 每個 段 由星號(*) 或者 美元符號($)開頭, 回車換行符(\r\n)結尾, 中間是不同含義的數據.
-
以星號開頭的段稱爲 頭段, 以美元符號開頭的段成爲 數據段.
-
不管是 redis 操作指令(比如 set、 get 等), 還是指令後面跟的操作數, 統稱爲 參數, 比如
set username zhangsan
這條命令中就包含了 3 個參數. -
頭段中的數據位表示傳輸的 參數個數, 數據段中的數據位表示爲 參數的長度 或者 具體的參數值.
示例如下:
用 Java 實現 redis 客戶端
以下是測試代碼:
public class App {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("localhost", 6379);
OutputStream out = socket.getOutputStream();
auth(out);
set(out);
//get(out);
//lPush(out);
InputStream inputStream = socket.getInputStream();
byte[] buf = new byte[1024];
while (inputStream.read(buf)!=-1) {
System.out.println(new String(buf));
}
}
// 認證 auth
public static void auth(OutputStream os) throws IOException {
String s = "*2\r\n$4\r\nAUTH\r\n$11\r\nQpLpYnh619!\r\n";
os.write(s.getBytes(StandardCharsets.UTF_8));
os.flush();
}
// SET USERNAME ZHANGSAN
public static void set(OutputStream os) throws IOException {
String s = "*3\r\n$3\r\nSET\r\n$8\r\nUSERNAME\r\n$8\r\nZHANGSAN\r\n";
os.write(s.getBytes(StandardCharsets.UTF_8));
os.flush();
}
// GET USERNAME
public static void get(OutputStream os) throws IOException {
String s = "*2\r\n$3\r\nGET\r\n$8\r\nUSERNAME\r\n";
os.write(s.getBytes(StandardCharsets.UTF_8));
os.flush();
}
// LPUSH food apple
public static void lPush(OutputStream os) throws IOException {
String s = "*3\r\n$5\r\nLPUSH\r\n$4\r\nfood\r\n$5\r\napple\r\n";
os.write(s.getBytes(StandardCharsets.UTF_8));
os.flush();
}
// 其他
}
關於抓包
實踐過程中, 是用 tcpdump 命令 + wireshark 軟件進行抓包分析. 兩者的安裝及詳細使用方法, 請自行了解.
- 通過 tcpdump 命令抓取 redis 服務端所在機器的網絡數據包
// 抓取 eth0 網卡, 端口爲 6379 的數據, 然後保存到 redis_6379.pcap 文件下.
tcpdump port 6379 -i eth0 -w redis_6379.pcap
-
安裝 wireshark 及解析 redis 協議的插件
可以參考 這篇教程
-
將 redis_6379.pcap 文件轉移到本機, 用 wireshark 軟件打開.
- 右鍵 follw -> TCP Stream