3. Redis的通信協(xié)議
先貼一個 官方文檔
3.1 RESP
RESP(redis Serialization Protocol)是Redis的序列化協(xié)議精盅,主要優(yōu)勢在于:
- 實現(xiàn)過程簡單
- 解析性能極好
- 可讀性強(qiáng)
RESP可序列化不同的數(shù)據(jù)類型福压,包括:簡單字符串、錯誤類型巢块、整數(shù)、批量字符串和數(shù)組。請求從客戶端發(fā)送到Redis服務(wù)器,作為表示要執(zhí)行命令的參數(shù)的字符串?dāng)?shù)組众弓,Redis-server會使用特定的數(shù)據(jù)類型進(jìn)行回復(fù)。
RESP是二進(jìn)制安全的隔箍,不需要處理從一個進(jìn)程傳輸?shù)搅硪粋€進(jìn)程的批量數(shù)據(jù)谓娃,因為它使用前綴來確定是否傳輸批量數(shù)據(jù)。
注意:RESP 雖然是為 Redis 設(shè)計的蜒滩,但是同樣也可以用于其他 C/S 的軟件滨达。Redis Cluster使用不同的二進(jìn)制協(xié)議(gossip)奶稠,以便在節(jié)點之間交換消息。
Redis協(xié)議將傳輸?shù)慕Y(jié)構(gòu)數(shù)據(jù)分為5種最小單元類型捡遍,單元結(jié)束時統(tǒng)一加上回車換行符"\r\n"(CRLF)結(jié)束锌订。
- "+"表示簡單字符串 Simple Strings,即:單行字符串
- "$"表示批量字符串Bulk Strings画株,后跟字符串長度
- ":"表示整數(shù)
- "-"表示錯誤消息
- "*"表示數(shù)組
3.2 驗證RESP
SET key value #對應(yīng)的resp通信協(xié)議串
*3
$3
SET
$3
key
$5
value
第一次看到這個通信協(xié)議串辆飘,看不懂不必?fù)?dān)心,我們按照RESP的協(xié)議說明慢慢看谓传,并且下文會有詳細(xì)的講解蜈项。
這里大概翻譯一下這段傳輸?shù)臄?shù)據(jù)含義:
- 第一行
*3
表示這條發(fā)給Redis server的命令是數(shù)組,數(shù)組有3個元素(其實就是SET续挟、key紧卒、value這仨字符串);
后面的6行數(shù)據(jù)诗祸,分別是對數(shù)組三個元素的表示跑芳,每個元素用兩行; - 數(shù)組第一個元素:<3`代表Bulk Strings字符串長度為3直颅,內(nèi)容是SET博个。
- 數(shù)組第二個元素:<3`代表Bulk Strings字符串長度為3,內(nèi)容是key功偿。
- 數(shù)組第三個元素:
$5 value``$5
代表Bulk Strings字符串長度為5坡倔,內(nèi)容是value。
3.3 具體類型說明
3.3.1簡單字符串Simple Strings
簡單字符串按以下方式編碼:+
字符脖含,后跟不能包含CR或LF字符的字符串(不允許換行),由CRLF終止(即“\r\n”)投蝉。
Simple Strings用于以最小的開銷养葵、傳輸非二進(jìn)制安全字符串。例如瘩缆,許多Redis命令在成功時僅回復(fù)“OK”关拒,因為RESP Simple String使用以下5個字節(jié)進(jìn)行編碼:
+OK\r\n
當(dāng)Redis使用Simple String回復(fù)時,該字符串由'+'之后的第一個字符組成庸娱,直到字符串結(jié)尾着绊,不包括最終的CRLF字節(jié)。
3.3.2 RESP錯誤
RESP具有特定的錯誤數(shù)據(jù)類型熟尉。實際上錯誤與RESP Simple Strings完全相同归露,但第一個字符是減-
字符而不是加號。RESP中簡單字符串和錯誤之間的真正區(qū)別在于客戶端將錯誤視為異常斤儿,組成錯誤類型的字符串是錯誤消息本身剧包。
基本格式是:-ERR errorMsg\r\n
錯誤回復(fù)僅在發(fā)生錯誤時發(fā)送恐锦,例如,如果你嘗試對錯誤的數(shù)據(jù)類型執(zhí)行操作疆液,或者命令不存在等等一铅。收到錯誤答復(fù)時,庫客戶端應(yīng)引發(fā)異常堕油。
以下是錯誤回復(fù)的示例:
-ERR unknown command 'foobar'
-WRONGTYPE Operation against a key holding the wrong kind of value
“-”之后的第一個單詞潘飘,直到第一個空格或換行符,表示返回的錯誤類型掉缺。這只是Redis使用的約定卜录,不是RESP錯誤格式的一部分。
例如攀圈,ERR是一般錯誤暴凑,而WRONGTYPE更具體的錯誤意味著客戶端嘗試對錯誤的數(shù)據(jù)類型執(zhí)行操作。這稱為錯誤前綴赘来,是一種允許客戶端理解服務(wù)器返回的錯誤類型的方法现喳,而不依賴于給定的確切消息,這可能隨時間而變化犬辰。
下面是幾個使用redis-cli的實際錯誤的例子:
127.0.0.1:6379> TaoBeier
-ERR unknown command 'TaoBeier'\r\n # 服務(wù)端實際返回, 下同
---
(error) ERR unknown command 'TaoBeier' # redis-cli 客戶端顯示, 下同
127.0.0.1:6379> set name TaoBeier love
-ERR syntax error\r\n
---
(error) ERR syntax error
客戶端實現(xiàn)可以針對不同的錯誤返回不同類型的異常嗦篱,或者可以通過直接將錯誤名稱作為字符串提供給調(diào)用者來提供捕獲錯誤的通用方法。
但是幌缝,錯誤類型很少有用灸促,并且有限的客戶端實現(xiàn)可能只是返回一般的錯誤條件,例如false涵卵。
3.3.3整數(shù)類型
此類型只是一個CRLF終止的字符串浴栽,表示一個以:
字節(jié)為前綴的整數(shù)。例如:0 \r\n
或:1000 \r\n
是整數(shù)回復(fù)轿偎。
很多Redis命令返回RESP整數(shù)類型典鸡,比如INCR,LLEN和LASTSAVE坏晦。
返回的整數(shù)沒有特殊含義萝玷,它只是INCR的增量數(shù),LASTSAVE的UNIX時間等等昆婿。但是球碉,返回的整數(shù)保證在有符號的64位整數(shù)范圍內(nèi)。
整數(shù)回復(fù)也被廣泛使用以返回真或假仓蛆。例如睁冬,EXISTS或SISMEMBER之類的命令將返回1表示true,0表示false表示看疙。
如果操作實際執(zhí)行痴突,其他命令如SADD搂蜓,SREM和SETNX將返回1,否則返回0辽装。
下面的命令都是整數(shù)類型回復(fù):SETNX帮碰,DEL, EXISTS拾积,INCR殉挽,INCRBY,DECR拓巧,DECRBY斯碌,DBSIZE,LASTSAVE肛度, RENAMENX傻唾,MOVE,LLEN承耿,SADD冠骄,SREM,SISMEMBER加袋,SCARD凛辣。
3.3.4 Bulk Strings類型
翻譯過來,是指批量职烧、多行字符串扁誓。
Bulk Strings用于表示長度最大為512MB的單個二進(jìn)制安全字符串。
批量字符串按以下方式編碼:
- 一個
$
字節(jié)后跟組成字符串的字節(jié)數(shù)(一個前綴長度)蚀之,由CRLF終止蝗敢。 - 實際的字符串?dāng)?shù)據(jù)。
- 最終的CRLF足删。
所以字符串“foobar”的編碼如下:
$6\r\n
foobar\r\n"
一個完整的Bulk Strings前普,主要包括兩行:
第一行,$后面跟上字符串長度壹堰;
第二行,就是實際的字符串骡湖。
如下面執(zhí)行set贱纠、get的例子:
127.0.0.1:6379> set site ljheee
+OK\r\n # 服務(wù)端實際返回, 下同
---
OK # redis-cli 客戶端顯示, 下同
127.0.0.1:6379> get site
$6\r\
ljheee\r\n
---
"ljheee"
在執(zhí)行set site value
時,客戶端給Redis server發(fā)送RESP命令后响蕴,Redis server返回的是simple strings類型+OK\r\n
谆焊,redis-cli命令行客戶端給我們只顯示了有效字符、省略了最后的CRLF浦夷。
在執(zhí)行get site
時辖试,Redis server返回的是Bulk Strings類型辜王,第一行$6
代表site對應(yīng)的value值length為6,第二行是實際value值罐孝。
當(dāng)只是一個空字符串時呐馆,表示為:$0\r\n
Bulk Strings也可用于使用用于表示Null值的特殊格式來表示值的不存在。在這種特殊格式中莲兢,長度為-1汹来,并且沒有數(shù)據(jù),因此Null表示為:$-1\r\n
改艇,這稱為Null Bulk String收班。
3.3.5 數(shù)組類型
客戶端使用數(shù)組、將命令發(fā)送到Redis服務(wù)器谒兄。類似地摔桦,某些Redis命令將元素集合返回給客戶端使用數(shù)組類型回復(fù)。如LRANGE命令承疲,它返回元素列表其實就是數(shù)組類型邻耕。
RESP數(shù)組使用以下格式發(fā)送:
- 它以 “*” 開頭,后面跟著返回元素的個數(shù)纪隙,后跟CRLF赊豌。
- 然后就是數(shù)組中各元素自己的類型了,數(shù)組每個元素可以是任意的RESP類型绵咱。
最典型的是 LRRANGE
命令碘饼,返回的就是數(shù)組類型
LRANGE info 0 -1
*2\r\n
$3\r\
abc\r\n
$6\r\n
ljheee\r\n
--- # 實際redis-cli顯示
1) "abc"
2) "ljheee"
返回的結(jié)果,*2代表數(shù)組長度為2悲伶,數(shù)組的第一個元素$3
是長度為3的字符串a(chǎn)bc艾恼;數(shù)組的第二個元素$6
是長度為6的字符串ljheee。