Redis是開源的、基於內存的數據結構存儲系統,可用做數據庫、緩存以及消息代理方面。Redis支持許多種數據結構,並內置了豐富的諸如冗餘、腳本、事務、持久化等功能,深受業界喜好,被各類業務系統普遍使用。爲了方便使用,Redis官網推薦了針對各類編程語言的多種客戶端,支持java、c#、python、c++等主流編程語言。那麼你們會問,既然Redis客戶端已經這麼豐富了,爲何還要嘗試本身編寫客戶端?個人見解是,知己知彼,本身嘗試製做Redis客戶端,不只能夠加深對Redis的瞭解,並且能夠通曉Redis客戶端的原理,爲從此的更好地使用、乃至定製改造Redis做好充分準備。java
要想親自開發Redis客戶端,須要如下知識:
一、網絡編程基礎
二、熟悉Redis協議
三、瞭解Redis的基本操做
另外文中的例子將會採用java編寫,所以最好有基本的java編程知識。python
本文面向Redis各層次使用者。c++
Redis協議被稱爲:RESP (REdis Serialization Protocol),客戶端經過TCP協議鏈接到客戶端的6379端口(默認端口)。
RESP協議是在Redis1.2中引入的,不過如今已是Redis2.0中的標準協議了。因此你應該再Redis客戶端中實現這個協議。git
RESP實際上是一個序列化協議,支持簡單字符串、錯誤、整數、整塊字符串和數組。數據類型依賴頭文字,分別表示以下:
簡單字符串的頭文字是「+」
錯誤的頭文字是「-」
整數的頭文字是「:」
整塊字符串的頭文字是「$」
數組的頭文字是「*」github
客戶端向Redis服務器發送命令,以RESP整塊字符串數組的形式。redis
服務器端根據命令的結果,選擇適宜的一種RESP類型返回數據庫
簡單字符串是以半角加號開頭,後跟隨着不含回車換行的字符串,而後以回車換行結尾。
舉例以下:+OK\r\n
簡單字符串是非二進制安全的,若是須要二進制安全,可以使用「整塊字符串」。編程
錯誤和簡單字符串相似,但頭文字換成半角減號了。後面跟隨的文字,能夠視爲錯誤消息內容。
舉例以下:
-ERR unknown command 'foobar'
-WRONGTYPE Operation against a key holding the wrong kind of valuec#
整數與簡單字符串相似,頭文字爲半角冒號。
舉例以下:
:0\r\n
:1000\r\n數組
整塊字符串能夠用來標示二進制安全的、最大512MB長度的字符串。它以$符號開頭,後跟隨實際字符串長度,以回車換行結尾,後跟隨實際字符串,再最終以回車換行結尾。
舉例以下:
$6\r\nfoobar\r\n
空字符串表現形式以下:$0\r\n\r\n
nil表現形式以下:$-1\r\n\r\n
數組以半角星號開頭,後接數組中元素個數,而後以回車換行結尾,而後後接各個元素。
舉例以下:
空數組:*0\r\n
包含兩個整塊字符串的數組:*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n
包含三個整數的數組:*3\r\n:1\r\n:2\r\n:3\r\n
數組還支持嵌套。
要實現和Redis服務端通訊,首先須要與Redis服務端創建TCP通訊鏈接,而後使用上述的RESP協議,將想要執行的Redis命令發送至服務端,並等待服務端響應,而後接收到響應結果,展現給用戶。
如下代碼實現了一個簡單的獲取info的操做。
package my_redis_client; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import java.nio.CharBuffer; /** * Hello world! * */ public class App { public static void main( String[] args ) { //定義redis服務端默認端口 int port = 6379; Socket socket = null; BufferedReader in = null; PrintWriter out = null; try { //建立tcp鏈接 socket = new Socket("localhost", port); in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out = new PrintWriter(socket.getOutputStream(), true); //傳送info命令 //客戶端向Redis服務器發送命令,以RESP整塊字符串數組的形式 out.println("*1\r\n$4\r\ninfo\r\n"); System.out.println("Redis command wat sent successfully."); //接收服務器的回覆 CharBuffer response = CharBuffer.allocate(1024); int readedLen = in.read(response); String responseBody = response.flip().toString(); //輸出服務器的回覆 System.out.println(responseBody); } catch(Exception e) { e.printStackTrace(); } finally { //最後關閉相關的流 if (out != null){ out.close(); out = null; } if (in != null) { try { in.close(); } catch(IOException e){ e.printStackTrace(); } in = null; } if (socket != null) { try { socket.close(); } catch(IOException e){ e.printStackTrace(); } socket = null; } } } }
運行後,系統將會在命令行界面輸出info的執行結果。
根據上述代碼所描述的方法,就能夠繼續擴展客戶端的功能,實現Redis各類命令了。
https://github.com/yourcaptai...
<dependency> <groupId>net.yesdata</groupId> <artifactId>dudu-RESP-interpreter</artifactId> <version>1.0.4</version> </dependency>