Redis通訊協定(protocol)_Redis

來源:互聯網
上載者:User
Redis通訊協定(protocol)

本文檔翻譯自: http://redis.io/topics/protocol 。

Redis 協議在以下三個目標之間進行折中: 易於實現 可以高效地被電腦分析(parse) 可以很容易地被人類讀懂 網路層

用戶端和伺服器通過 TCP 串連來進行資料互動, 伺服器預設的連接埠號碼為 6379 。

用戶端和伺服器發送的命令或資料一律以 \r\n (CRLF)結尾。 請求

Redis 伺服器接受命令以及命令的參數。

伺服器會在接到命令之後,對命令進行處理,並將命令的回複傳送回用戶端。 新版統一請求協議

新版統一請求協議在 Redis 1.2 版本中引入, 並最終在 Redis 2.0 版本成為 Redis 伺服器通訊的標準方式。

你的 Redis 用戶端應該按照這個新版協議來進行實現。

在這個協議中, 所有發送至 Redis 伺服器的參數都是二進位安全(binary safe)的。

以下是這個協議的一般形式:

*<參數數量> CR LF$<參數 1 的位元組數量> CR LF<參數 1 的資料> CR LF...$<參數 N 的位元組數量> CR LF<參數 N 的資料> CR LF

譯註:命令本身也作為協議的其中一個參數來發送。

舉個例子, 以下是一個命令協議的列印版本:

*3$3SET$5mykey$7myvalue

這個命令的實際協議值如下:

"*3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$7\r\nmyvalue\r\n"

稍後我們會看到, 這種格式除了用作命令請求協議之外, 也用在命令的回複協議中: 這種只有一個參數的回複格式被稱為批量回複(Bulk Reply)。

統一協議請求原本是用在回複協議中, 用於將列表的多個項返回給用戶端的, 這種回複格式被稱為多條批量回複(Multi Bulk Reply)。

一個多條批量回複以 *<argc>\r\n 為首碼, 後跟多條不同的批量回複, 其中 argc 為這些批量回複的數量。 回複

Redis 命令會返回多種不同類型的回複。

通過檢查伺服器發回資料的第一個位元組, 可以確定這個回複是什麼類型: 狀態回複(status reply)的第一個位元組是 "+" 錯誤回複(error reply)的第一個位元組是 "-" 整數回複(integer reply)的第一個位元組是 ":" 批量回複(bulk reply)的第一個位元組是 "$" 多條批量回複(multi bulk reply)的第一個位元組是 "*" 狀態回複

一個狀態回複(或者單行回複,single line reply)是一段以 "+" 開始、 "\r\n" 結尾的單行字串。

以下是一個狀態回複的例子:

+OK

用戶端庫應該返回 "+" 號之後的所有內容。 比如在在上面的這個例子中, 用戶端就應該返回字串 "OK" 。

狀態回複通常由那些不需要返回資料的命令返回,這種回複不是二進位安全的,它也不能包含新行。

狀態回複的額外開銷非常少,只需要三個位元組(開頭的 "+" 和結尾的 CRLF)。 錯誤回複

錯誤回複和狀態回複非常相似, 它們之間的唯一區別是, 錯誤回複的第一個位元組是 "-" , 而狀態回複的第一個位元組是 "+" 。

錯誤回複只在某些地方出現問題時發送: 比如說, 當使用者對不正確的資料類型執行命令, 或者執行一個不存在的命令, 等等。

一個用戶端庫應該在收到錯誤回複時產生一個異常。

以下是兩個錯誤回複的例子:

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

在 "-" 之後,直到遇到第一個空格或新行為止,這中間的內容表示所返回錯誤的類型。

ERR 是一個通用錯誤,而 WRONGTYPE 則是一個更特定的錯誤。 一個用戶端實現可以為不同類型的錯誤產生不同類型的異常, 或者提供一種通用的方式, 讓調用者可以通過提供字串形式的錯誤名來捕捉(trap)不同的錯誤。

不過這些特性用得並不多, 所以並不是特別重要, 一個受限的(limited)用戶端可以通過簡單地返回一個邏輯假(false)來表示一個通用的錯誤條件。 整數回複

整數回複就是一個以 ":" 開頭, CRLF 結尾的字串表示的整數。

比如說, ":0\r\n" 和 ":1000\r\n" 都是整數回複。

返回整數回複的其中兩個命令是 INCR 和 LASTSAVE 。 被返回的整數沒有什麼特殊的含義, INCR 返回鍵的一個自增後的整數值, 而 LASTSAVE 則返回一個 UNIX 時間戳記, 傳回值的唯一限制是這些數必須能夠用 64 位元有符號整數表示。

整數回複也被廣泛地用於表示邏輯真和邏輯假: 比如 EXISTS 和 SISMEMBER 都用傳回值 1 表示真, 0 表示假。

其他一些命令, 比如 SADD 、 SREM 和 SETNX , 只在操作真正被執行了的時候, 才返回 1 , 否則返回 0 。

以下命令都返回整數回複: SETNX 、 DEL 、 EXISTS 、 INCR 、 INCRBY 、 DECR 、 DECRBY 、 DBSIZE 、 LASTSAVE 、RENAMENX 、 MOVE 、 LLEN 、 SADD 、 SREM 、 SISMEMBER 、 SCARD 。 批量回複

伺服器使用批量回複來返回二進位安全的字串,字串的最大長度為 512 MB 。

用戶端:GET mykey伺服器:foobar

伺服器發送的內容中: 第一位元組為 "$" 符號 接下來跟著的是表示實際回複長度的數字值 之後跟著一個 CRLF 再後面跟著的是實際回複資料 最末尾是另一個 CRLF

對於前面的 GET 命令,伺服器實際發送的內容為:

"$6\r\nfoobar\r\n"

如果被請求的值不存在, 那麼批量回複會將特殊值 -1 用作回複的長度值, 就像這樣:

用戶端:GET non-existing-key伺服器:$-1

這種回複稱為空白批量回複(NULL Bulk Reply)。

當請求對象不存在時,用戶端應該返回Null 物件,而不是Null 字元串: 比如 Ruby 庫應該返回 nil , 而 C 庫應該返回 NULL (或者在回複對象中設定一個特殊標誌), 諸如此類。 多條批量回複

像 LRANGE 這樣的命令需要返回多個值, 這一目標可以通過多條批量回複來完成。

多條批量回複是由多個回複組成的數組, 數組中的每個元素都可以是任意類型的回複, 包括多條批量回複本身。

多條批量回複的第一個位元組為 "*" , 後跟一個字串表示的整數值, 這個值記錄了多條批量回複所包含的回複數量, 再後面是一個 CRLF 。

用戶端: LRANGE mylist 0 3伺服器: *4伺服器: $3伺服器: foo伺服器: $3伺服器: bar伺服器: $5伺服器: Hello伺服器: $5伺服器: World

在上面的樣本中,伺服器發送的所有字串都由 CRLF 結尾。

正如你所見到的那樣, 多條批量回複所使用的格式, 和用戶端發送命令時使用的統一請求協議的格式一模一樣。 它們之間的唯一區別是: 統一請求協議只發送批量回複。 而伺服器應答命令時所發送的多條批量回複,則可以包含任意類型的回複。

以下例子展示了一個多條批量回複, 回複中包含四個整數值, 以及一個二進位安全字串:

*5\r\n:1\r\n:2\r\n:3\r\n:4\r\n$6\r\nfoobar\r\n

在回複的第一行, 伺服器發送 *5\r\n , 表示這個多條批量回複包含 5 條回複, 再後面跟著的則是 5 條回複的本文。

多條批量回複也可以是空白的(empty), 就像這樣:

用戶端: LRANGE nokey 0 1伺服器: *0\r\n

無內容的多條批量回複(null multi bulk reply)也是存在的, 比如當 BLPOP 命令的阻塞時間超過最大時限時, 它就返回一個無內容的多條批量回複, 這個回複的計數值為 -1 :

用戶端: BLPOP key 1伺服器: *-1\r\n

用戶端庫應該區別對待空白多條回複和無內容多條回複: 當 Redis 返回一個無內容多條回複時, 用戶端庫應該返回一個 null 對象, 而不是一個空數組。 多條批量回複中的空元素

多條批量回複中的元素可以將自身的長度設定為 -1 , 從而表示該元素不存在, 並且也不是一個空白字串(empty string)。

當 SORT 命令使用 GET pattern 選項對一個不存在的鍵進行操作時, 就會發生多條批量回複中帶有空白元素的情況。

以下例子展示了一個包含空元素的多重批量回複:

伺服器: *3伺服器: $3伺服器: foo伺服器: $-1伺服器: $3伺服器: bar

其中, 回複中的第二個元素為空白。

對於這個回複, 用戶端庫應該返回類似於這樣的回複:

["foo", nil, "bar"]
多命令和流水線

用戶端可以通過流水線, 在一次寫入操作中發送多個命令: 在發送新命令之前, 無須閱讀前一個命令的回複。 多個命令的回複會在最後一併返回。 內聯命令

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

以下是一個用戶端和伺服器使用內聯命令來進行互動的例子:

用戶端: PING伺服器: +PONG

以下另一個返回整數值的內聯命令的例子:

用戶端: EXISTS somekey伺服器: :0

因為沒有了統一請求協議中的 "*" 項來聲明參數的數量, 所以在 telnet 會話輸入命令的時候, 必須使用空格來分割各個參數, 伺服器在接收到資料之後, 會按空格對使用者的輸入進行分析(parse), 並擷取其中的命令參數。 高效能 Redis 協議分析器

儘管 Redis 的協議非常利於人類閱讀, 定義也很簡單, 但這個協議的實現效能仍然可以和二進位協議一樣快。

因為 Redis 協議將資料的長度放在資料本文之前, 所以程式無須像 JSON 那樣, 為了尋找某個特殊字元而掃描整個 payload , 也無須對發送至伺服器的 payload 進行轉義(quote)。

程式可以在對協議文本中的各個字元進行處理的同時, 尋找 CR 字元, 並計算出批量回複或多條批量回複的長度, 就像這樣:

#include <stdio.h>int main(void) {    unsigned char *p = "$123\r\n";    int len = 0;    p++;    while(*p != '\r') {        len = (len*10)+(*p - '0');        p++;    }    /* Now p points at '\r', and the len is in bulk_len. */    printf("%d\n", len);    return 0;}

得到了批量回複或多條批量回複的長度之後, 程式只需調用一次 read 函數, 就可以將回複的本文資料全部讀入到記憶體中, 而無須對這些資料做任何的處理。

在回複最末尾的 CR 和 LF 不作處理,丟棄它們。

Redis 協議的實現效能可以和二進位協議的實現效能相媲美, 並且由於 Redis 協議的簡單性, 大部分進階語言都可以輕易地實現這個協議, 這使得用戶端軟體的 bug 數量大大減少。


from: http://redisdoc.com/topic/protocol.html

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.