Redis奇幻之旅(三)3. Redis的通信協(xié)議

3. Redis的通信協(xié)議

先貼一個(gè) 官方文檔

3.1 RESP

RESP(redis Serialization Protocol)是Redis的序列化協(xié)議,主要優(yōu)勢(shì)在于:

- 實(shí)現(xiàn)過(guò)程簡(jiǎn)單
- 解析性能極好
- 可讀性強(qiáng)

RESP可序列化不同的數(shù)據(jù)類型,包括:簡(jiǎn)單字符串、錯(cuò)誤類型、整數(shù)、批量字符串和數(shù)組。請(qǐng)求從客戶端發(fā)送到Redis服務(wù)器,作為表示要執(zhí)行命令的參數(shù)的字符串?dāng)?shù)組,Redis-server會(huì)使用特定的數(shù)據(jù)類型進(jìn)行回復(fù)。

RESP是二進(jìn)制安全的,不需要處理從一個(gè)進(jìn)程傳輸?shù)搅硪粋€(gè)進(jìn)程的批量數(shù)據(jù),因?yàn)樗褂们熬Y來(lái)確定是否傳輸批量數(shù)據(jù)。

注意:RESP 雖然是為 Redis 設(shè)計(jì)的,但是同樣也可以用于其他 C/S 的軟件。Redis Cluster使用不同的二進(jìn)制協(xié)議(gossip),以便在節(jié)點(diǎn)之間交換消息。

Redis協(xié)議將傳輸?shù)慕Y(jié)構(gòu)數(shù)據(jù)分為5種最小單元類型,單元結(jié)束時(shí)統(tǒng)一加上回車換行符"\r\n"(CRLF)結(jié)束。

  • "+"表示簡(jiǎn)單字符串 Simple Strings,即:?jiǎn)涡凶址?/li>
  • "$"表示批量字符串Bulk Strings,后跟字符串長(zhǎng)度
  • ":"表示整數(shù)
  • "-"表示錯(cuò)誤消息
  • "*"表示數(shù)組

3.2 驗(yàn)證RESP

SET key value #對(duì)應(yīng)的resp通信協(xié)議串

*3
$3
SET
$3
key
$5
value

第一次看到這個(gè)通信協(xié)議串,看不懂不必?fù)?dān)心,我們按照RESP的協(xié)議說(shuō)明慢慢看,并且下文會(huì)有詳細(xì)的講解。
這里大概翻譯一下這段傳輸?shù)臄?shù)據(jù)含義:

  • 第一行*3表示這條發(fā)給Redis server的命令是數(shù)組,數(shù)組有3個(gè)元素(其實(shí)就是SET、key、value這仨字符串);
    后面的6行數(shù)據(jù),分別是對(duì)數(shù)組三個(gè)元素的表示,每個(gè)元素用兩行;
  • 數(shù)組第一個(gè)元素:<3 SET> `3`代表Bulk Strings字符串長(zhǎng)度為3,內(nèi)容是SET。
  • 數(shù)組第二個(gè)元素:<3 key> `3`代表Bulk Strings字符串長(zhǎng)度為3,內(nèi)容是key。
  • 數(shù)組第三個(gè)元素:$5 value``$5代表Bulk Strings字符串長(zhǎng)度為5,內(nèi)容是value。

3.3 具體類型說(shuō)明

3.3.1簡(jiǎn)單字符串Simple Strings

簡(jiǎn)單字符串按以下方式編碼:+字符,后跟不能包含CR或LF字符的字符串(不允許換行),由CRLF終止(即“\r\n”)。
Simple Strings用于以最小的開銷、傳輸非二進(jìn)制安全字符串。例如,許多Redis命令在成功時(shí)僅回復(fù)“OK”,因?yàn)镽ESP Simple String使用以下5個(gè)字節(jié)進(jìn)行編碼:
+OK\r\n

當(dāng)Redis使用Simple String回復(fù)時(shí),該字符串由'+'之后的第一個(gè)字符組成,直到字符串結(jié)尾,不包括最終的CRLF字節(jié)。

3.3.2 RESP錯(cuò)誤

RESP具有特定的錯(cuò)誤數(shù)據(jù)類型。實(shí)際上錯(cuò)誤與RESP Simple Strings完全相同,但第一個(gè)字符是減-字符而不是加號(hào)。RESP中簡(jiǎn)單字符串和錯(cuò)誤之間的真正區(qū)別在于客戶端將錯(cuò)誤視為異常,組成錯(cuò)誤類型的字符串是錯(cuò)誤消息本身。
基本格式是:-ERR errorMsg\r\n

錯(cuò)誤回復(fù)僅在發(fā)生錯(cuò)誤時(shí)發(fā)送,例如,如果你嘗試對(duì)錯(cuò)誤的數(shù)據(jù)類型執(zhí)行操作,或者命令不存在等等。收到錯(cuò)誤答復(fù)時(shí),庫(kù)客戶端應(yīng)引發(fā)異常。
以下是錯(cuò)誤回復(fù)的示例:

-ERR unknown command 'foobar'
-WRONGTYPE Operation against a key holding the wrong kind of value

“-”之后的第一個(gè)單詞,直到第一個(gè)空格或換行符,表示返回的錯(cuò)誤類型。這只是Redis使用的約定,不是RESP錯(cuò)誤格式的一部分。
例如,ERR是一般錯(cuò)誤,而WRONGTYPE更具體的錯(cuò)誤意味著客戶端嘗試對(duì)錯(cuò)誤的數(shù)據(jù)類型執(zhí)行操作。這稱為錯(cuò)誤前綴,是一種允許客戶端理解服務(wù)器返回的錯(cuò)誤類型的方法,而不依賴于給定的確切消息,這可能隨時(shí)間而變化。

下面是幾個(gè)使用redis-cli的實(shí)際錯(cuò)誤的例子:

127.0.0.1:6379> TaoBeier
-ERR unknown command 'TaoBeier'\r\n  # 服務(wù)端實(shí)際返回, 下同
---
(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

客戶端實(shí)現(xiàn)可以針對(duì)不同的錯(cuò)誤返回不同類型的異常,或者可以通過(guò)直接將錯(cuò)誤名稱作為字符串提供給調(diào)用者來(lái)提供捕獲錯(cuò)誤的通用方法。
但是,錯(cuò)誤類型很少有用,并且有限的客戶端實(shí)現(xiàn)可能只是返回一般的錯(cuò)誤條件,例如false。

3.3.3整數(shù)類型

此類型只是一個(gè)CRLF終止的字符串,表示一個(gè)以字節(jié)為前綴的整數(shù)。例如:0 \r\n:1000 \r\n是整數(shù)回復(fù)。

很多Redis命令返回RESP整數(shù)類型,比如INCR,LLEN和LASTSAVE。
返回的整數(shù)沒(méi)有特殊含義,它只是INCR的增量數(shù),LASTSAVE的UNIX時(shí)間等等。但是,返回的整數(shù)保證在有符號(hào)的64位整數(shù)范圍內(nèi)。

整數(shù)回復(fù)也被廣泛使用以返回真或假。例如,EXISTS或SISMEMBER之類的命令將返回1表示true,0表示false表示。
如果操作實(shí)際執(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類型

翻譯過(guò)來(lái),是指批量、多行字符串。
Bulk Strings用于表示長(zhǎng)度最大為512MB的單個(gè)二進(jìn)制安全字符串。
批量字符串按以下方式編碼:

  • 一個(gè)$字節(jié)后跟組成字符串的字節(jié)數(shù)(一個(gè)前綴長(zhǎng)度),由CRLF終止。
  • 實(shí)際的字符串?dāng)?shù)據(jù)。
  • 最終的CRLF。
    所以字符串“foobar”的編碼如下:
$6\r\n
foobar\r\n"

一個(gè)完整的Bulk Strings,主要包括兩行:
第一行,$后面跟上字符串長(zhǎng)度;
第二行,就是實(shí)際的字符串。
如下面執(zhí)行set、get的例子:

127.0.0.1:6379> set site ljheee
+OK\r\n  # 服務(wù)端實(shí)際返回, 下同
---
OK   # redis-cli 客戶端顯示, 下同
127.0.0.1:6379> get site
$6\r\
ljheee\r\n
---
"ljheee"

在執(zhí)行set site value時(shí),客戶端給Redis server發(fā)送RESP命令后,Redis server返回的是simple strings類型+OK\r\n,redis-cli命令行客戶端給我們只顯示了有效字符、省略了最后的CRLF。
在執(zhí)行get site時(shí),Redis server返回的是Bulk Strings類型,第一行$6代表site對(duì)應(yīng)的value值length為6,第二行是實(shí)際value值。

當(dāng)只是一個(gè)空字符串時(shí),表示為:$0\r\n
Bulk Strings也可用于使用用于表示Null值的特殊格式來(lái)表示值的不存在。在這種特殊格式中,長(zhǎng)度為-1,并且沒(méi)有數(shù)據(jù),因此Null表示為:$-1\r\n,這稱為Null Bulk String。

3.3.5 數(shù)組類型

客戶端使用數(shù)組、將命令發(fā)送到Redis服務(wù)器。類似地,某些Redis命令將元素集合返回給客戶端使用數(shù)組類型回復(fù)。如LRANGE命令,它返回元素列表其實(shí)就是數(shù)組類型。

RESP數(shù)組使用以下格式發(fā)送:

  • 它以 “*” 開頭,后面跟著返回元素的個(gè)數(shù),后跟CRLF。
  • 然后就是數(shù)組中各元素自己的類型了,數(shù)組每個(gè)元素可以是任意的RESP類型。

最典型的是 LRRANGE 命令,返回的就是數(shù)組類型

LRANGE info 0 -1
*2\r\n
$3\r\
abc\r\n
$6\r\n
ljheee\r\n
--- # 實(shí)際redis-cli顯示
1) "abc"
2) "ljheee"

返回的結(jié)果,*2代表數(shù)組長(zhǎng)度為2,數(shù)組的第一個(gè)元素$3是長(zhǎng)度為3的字符串a(chǎn)bc;數(shù)組的第二個(gè)元素$6是長(zhǎng)度為6的字符串ljheee。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者。

友情鏈接更多精彩內(nèi)容