【轉】redis 通訊協議詳解

原文: https://blog.csdn.net/u014608280/article/details/84586042redis

------------------------------------------------------數組

1、簡介安全

redis 客戶端和服務端之間通訊的協議是RESP(REdis Serialization Protocol)。傳輸層使用TCP。RESP的特色是:服務器

實現容易
解析快
人類可讀
2、數據類型 和協議格式


網絡

RESP其實是一個支持如下數據類型的序列化協議:簡單字符串(Simple Strings),錯誤(Errors),整數(Integers),批量字符串(Bulk String)和數組(Arrays)。編碼

RESP在Redis中用做請求 - 響應協議的方式以下:url

客戶端將命令做爲Bulk Strings的RESP數組發送到Redis服務器。
服務器根據命令實現回覆一種RESP類型。
在RESP中,某些數據的類型取決於第一個字節:

.net

對於簡單字符串,回覆的第一個字節是「+」
對於錯誤,回覆的第一個字節是「 - 」
對於整數,回覆的第一個字節是「:」
對於批量字符串,回覆的第一個字節是「$」
對於數組,回覆的第一個字節是「 *」
在RESP中,協議的不一樣部分始終以「\ r \ n」(CRLF)結束。




scala

3、請求格式blog

*<number of arguments> CR LF
$<number of bytes of argument 1> CR LF
<argument data> CR LF
...
$<number of bytes of argument N> CR LF
<argument data> CR LF
*<number of arguments> :字符串的個數





$<number of bytes of argument N> :第N個字符串的長度

<argument data> :字符串值

示例:

*3
$3
set
$5
key11
$7
value11
wireshark 抓包數據:






 

4、回覆格式

一、簡單字符串(Simple Strings)

+OK\r\n
+ 固定開始,\r\n固定結束, 中間即爲回覆的內容。

二、錯誤(Errors)

-Error message\r\n
相似簡單字符串,可是開頭用‘-’表示是錯誤信息。

Error 稱爲錯誤類型,「 - 」以後的第一個單詞,直到第一個空格或換行符 ,常見的有ERR、WRONGTYPE、NOSCRIPT等。

message 表示錯誤信息。

如下是一些redis返回的錯誤:

-ERR unknown command 'foobar'
-WRONGTYPE Operation against a key holding the wrong kind of value
-NOSCRIPT No matching script. Please use EVAL.
-READONLY You can't write against a read only slave.
-OOM command not allowed when used memory > 'maxmemory'.
-EXECABORT Transaction discarded because of previous errors.
-BUSYKEY Target key name already exists.
三、整數(Integers)






:1000\r\n
像INCR、LLEN、LASTSAVE等命令返回的都是整數表示增量編號、長度、時間。

像EXISTS或SISMEMBER之類類的命令將返回1表示true,0表示false

返回的整數保證在有符號的64位整數範圍內。

四、批量字符串(Bulk strings)

$6\r\nfoobar\r\n
Bulk Strings用於表示長度最大爲512 MB的單個二進制安全字符串。

批量字符串按如下方式編碼:

一個「$」字節後跟組成字符串的字節數(一個前綴長度),由CRLF終止。
實際的字符串數據。
最終的CRLF。 
$0\r\n\r\n
表示空字符串



$-1\r\n
表示NULL

五、數組(Arrays)

RESP數組使用如下格式發送:

一個*字符做爲第一個字節,後跟數組中的元素數做爲十進制數,後跟CRLF。
Array的每一個元素的附加RESP類型。
*0\r\n
表示空數組


*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n
表示"foo"和"bar" 兩個批量字符串數組

*-1\r\n
表示NULL數組

*2\r\n
*3\r\n
:1\r\n
:2\r\n
:3\r\n
*2\r\n
+Foo\r\n
-Bar\r\n
表示一個由兩個元素組成的數組,該數組包含三個整數1,2,3以及一個簡單字符串和一個錯誤的數組。







5、內聯命令

當你須要和 Redis 服務器進行溝通, 但又找不到 redis-cli , 而手上只有 telnet 的時候, 你能夠經過 Redis 特別爲這種情形而設的內聯命令格式來發送命令。

如下是一個客戶端和服務器使用內聯命令來進行交互的例子:

客戶端: PING
服務器: +PONG
如下另外一個返回整數值的內聯命令的例子:

客戶端: EXISTS somekey
服務器: :0
由於沒有了統一請求協議中的 "*" 項來聲明參數的數量, 因此在 telnet 會話輸入命令的時候, 必須使用空格來分割各個參數, 服務器在接收到數據以後, 會按空格對用戶的輸入進行分析(parse), 並獲取其中的命令參數。

經過wireshark抓包來看:

 

 

對比用redis_cli客戶端執行ping命令抓包

 

能夠看出只是請求格式改變了,應答的格式沒有改變。

6、多命令和流水線

客戶端能夠經過流水線, 在一次寫入操做中發送多個命令:

在發送新命令以前, 無須閱讀前一個命令的回覆。
多個命令的回覆會在最後一併返回。
7、訂閱和發佈

SUBSCRIBE、UNSUBSCRIBE  和 PUBLISH三個命令實現了發佈與訂閱信息泛型(Publish/Subscribe messaging paradigm), 在這個實現中, 發送者(發送信息的客戶端)不是將信息直接發送給特定的接收者(接收信息的客戶端), 而是將信息發送給頻道(channel), 而後由頻道將信息轉發給全部對這個頻道感興趣的訂閱者。

發送者無須知道任何關於訂閱者的信息, 而訂閱者也無須知道是那個客戶端給它發送信息, 它只要關注本身感興趣的頻道便可。

對發佈者和訂閱者進行解構(decoupling), 能夠極大地提升系統的擴展性(scalability), 並獲得一個更動態的網絡拓撲(network topology)。

好比說, 要訂閱頻道 foo 和 bar , 客戶端可使用頻道名字做爲參數來調用 SUBSCRIBE 命令:

redis> SUBSCRIBE foo bar
當有客戶端發送信息到這些頻道時, Redis 會將傳入的信息推送到全部訂閱這些頻道的客戶端裏面。

正在訂閱頻道的客戶端不該該發送除 SUBSCRIBE 和 UNSUBSCRIBE 以外的其餘命令。 其中, SUBSCRIBE 能夠用於訂閱更多頻道, 而 UNSUBSCRIBE 則能夠用於退訂已訂閱的一個或多個頻道。

SUBSCRIBE 和 UNSUBSCRIBE 的執行結果會以信息的形式返回, 客戶端能夠經過分析所接收信息的第一個元素, 從而判斷所收到的內容是一條真正的信息, 仍是 SUBSCRIBE 或 UNSUBSCRIBE 命令的操做結果。

頻道轉發的每條信息都是一條帶有三個元素的多條批量回復(multi-bulk reply)。

信息的第一個元素標識了信息的類型:

subscribe : 表示當前客戶端成功地訂閱了信息第二個元素所指示的頻道。 而信息的第三個元素則記錄了目前客戶端已訂閱頻道的總數。
unsubscribe : 表示當前客戶端成功地退訂了信息第二個元素所指示的頻道。 信息的第三個元素記錄了客戶端目前仍在訂閱的頻道數量。 當客戶端訂閱的頻道數量降爲 0 時, 客戶端再也不訂閱任何頻道, 它能夠像往常同樣, 執行任何 Redis 命令。
message : 表示這條信息是由某個客戶端執行 PUBLISH 命令所發送的, 真正的信息。 信息的第二個元素是信息來源的頻道, 而第三個元素則是信息的內容。
舉個例子, 若是客戶端執行如下命令:


redis> SUBSCRIBE first second
那麼它將收到如下回復:

1) "subscribe"
2) "first"
3) (integer) 1

1) "subscribe"
2) "second"
3) (integer) 2
若是在這時, 另外一個客戶端執行如下 PUBLISH 命令:






redis> PUBLISH second Hello
那麼以前訂閱了 second 頻道的客戶端將收到如下信息:

1) "message"
2) "second"
3) "hello"
當訂閱者決定退訂全部頻道時, 它能夠執行一個無參數的 UNSUBSCRIBE 命令:


redis> UNSUBSCRIBE
這個命令將接到如下回復:

1) "unsubscribe"2) "second"3) (integer) 1 1) "unsubscribe"2) "first"3) (integer) 0 ————————————————版權聲明:本文爲CSDN博主「耿小渣」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處連接及本聲明。原文連接:https://blog.csdn.net/u014608280/article/details/84586042

相關文章
相關標籤/搜索