RESP是以下幾點的折中:
RESP可以序列化不同的數據類型,如整數,字符串和數組,並有壹個特定的錯誤類型。請求以字符串數組的形式從客戶機發送到Redis服務器,該數組表示要執行的命令。Redis使用特定於命令的數據類型進行回復。
RESP是二進制安全的,它不需要處理從壹個進程傳輸到另壹個進程的批處理數據,因為它使用長度前綴來傳輸批處理數據。
註意:這裏描述的協議僅用於客戶端/服務器通信,Redis集群使用不同的二進制協議在節點之間交換信息。
客戶端通過創建端口號為6379的TCP連接到Redis服務器。
盡管從技術上講,RESP並不是特定於TCP的,但該協議僅用於Redis上下文(或等效的面向流的連接,如Unix套接字)TCP連接。
Redis接收由不同參數組成的命令。壹旦收到命令,它將被執行,並向客戶端發送回復。
這可能是最簡單的模型,但是,有兩個例外:
除了這兩個例外,Redis協議是壹個簡單的請求-響應協議。
Redis RESP協議是在v1.2版本中引入的,但它直到v2.0才成為與服務器通信的標準
RESP協議支持以下數據類型:簡單字符串、錯誤、整數、批量字符串和數組。
Redis以下列方式使用RESP作為請求-響應協議:
在RESP中,第壹個字節決定數據類型:
在RESP,協議的不同部分總是以\r\n (CRLF)結尾。
RESP使用壹種特殊的組合來表示空批量字符串或空數組:$-1 \ r \ n表示空批量字符串,而*-1\r\n表示空數組。請註意,$0\r\n和*0\r\n分別表示。
簡單字符串的編碼是以+號開頭,後跟不能包含CR或LF字符的字符串(即不允許換行符),最後以CRLF( \r\n)結尾。
簡單字符串以最小的開銷傳輸非二進制安全字符串。例如,許多Redis命令成功執行後,回復只有OK,簡單的RESP字符串將被編碼為5個字節:+OK\r\n
如果要傳輸二進制安全字符串,請使用批量字符串。
當Redis回復壹個簡單的字符串時,客戶端庫應該返回+號後第壹個字符之後的所有字符串(不包括CRLF字節)。
Redis有特定的錯誤類型,類似於簡單的字符串,除了第壹個字符是減號——而不是加號+。兩者真正的區別在於,客戶端將錯誤視為異常,而構成錯誤類型的字符串就是錯誤消息本身。
錯誤類型的基本格式是:
-錯誤消息\r\n
只有發生錯誤時才會回復錯誤,比如妳想對錯誤的數據類型執行命令,或者命令根本不存在。當客戶端收到錯誤回復時,它應該拋出壹個異常。
以下是錯誤回復的示例:
第壹個空格或新行的第壹個單詞的-符號表示返回的錯誤類型,這只是Redis使用的壹種約定,不是RESP錯誤格式的壹部分。
例如,ERR是壹個壹般錯誤,但WRONGTYPE是壹個更具體的錯誤,表明客戶端正在嘗試執行壹個操作來處理錯誤的類型。這稱為錯誤前綴,這是壹種允許客戶端知道服務器返回的錯誤類型而無需檢查確切的錯誤消息的方法。
客戶端實現可以針對不同的錯誤返回不同類型的異常,或者通過直接將錯誤名稱作為字符串提供給調用者來提供壹個通用的方法來捕捉錯誤。
然而,這種函數不應該被認為是關鍵的,因為它很少有用,有限的客戶端實現可能只是返回壹個常見的錯誤條件,如false。
此類型只是壹個以CRLF結尾的字符串,它表示壹個帶有前綴的整數,如:0\r\n和:1000\r\n
有許多Redis命令返回整數,如INCR、LLEN和LASTSAVE。返回的整數數據範圍是有符號的64位整數。
整數回復也可以用來表示真或假。例如,EXISTS或SISMEMBER將為true返回1,為false返回0。
其他命令如SADD、SREM和SETNX如果執行將返回1,否則返回0。
其他返回整數的命令:SETNX,DEL,EXISTS,INCR,INCRBY,DECR,DECRBY,DBSIZE,LASTSAVE,RENAMENX,MOVE,LLEN,SADD,SREM,SISMEMBER,SCARD。
批量字符串用於表示單個二進制安全字符串,最大長度為512MB。
批量字符串的編碼方法是:
因此,字符串hello編碼為:$5\r\nhello\r\n
空字符串編碼為:$0\r\n\r\n
RESP批量字符串也可以用特殊格式表示不存在(空)。這種格式,長度為-1,沒有數據:$-1\r\n,稱為NULL批量字符串。當服務器回復NULL批量字符串時,客戶端庫的API不應該返回空字符串,而應該返回nil對象。
客戶端使用RESP陣列向服務器發送命令。類似地,壹些向客戶端返回元素集合的命令使用RESP數組作為回復,比如LRANGE命令。重分析以下列格式發送:
因此,空數組的編碼是:*0\r\n
包含兩個元素“hello”和“world”的RESP數組編碼為:* 2 \ r \ n $ 5 \ r \ n hello \ r \ n $ 5 \ r \ n world \ r \ n
如妳所見*
數組可以包含不同的數據類型。例如,由四個整數和壹個批處理字符串組成的數組編碼為:(為了直觀起見,以換行符的形式呈現)。
第壹行* 5 \ r \ n表示有五個回復,然後讀取接下來的五個數組元素。
也存在有NULL值的數組(通常使用NULL批量字符串,由於歷史原因NULL以兩種格式存在)。例如,當BLPOP超時時,它將返回長度為-1的空數組:*-1 \ r \ n
嵌套數組也存在於RESP。例如,兩個嵌套數組的編碼結果是:
上面的編碼結果包含兩個元素的數組,第壹個元素是由(1,2,3)組成的子數組,第二個元素是由壹個Bulk字符串(+Hello)和壹個Error(-World)組成的數組。
數組中的單個元素可能為空。這在Redis回復中用於指示這些元素缺失,而不是空字符串。當SORT命令使用GET pattern子命令並且缺少鍵時,會發生這種情況。包含空元素的數組回復為:
以上編碼解析結果為:["hello ",nil," world"]。
妳可以根據上面幾節的介紹寫壹個Redis客戶端,詳細了解壹下客戶端和服務器的交互是如何進行的。
因此,典型的交互場景可能如下:
為了獲得存儲在mylist中的列表的長度,客戶端向服務器發送命令LLEN mylist,然後服務器用整數回復來回復客戶端:
協議規範
Redis系列第壹部分中的SPEC協議