一起了解Redis是如何通信的

Redis協議規範

Redis客戶端使用稱爲RESP(REdis序列化協議)的協議與Redis 服務器進行通信。雖然該協議是專爲Redis設計的,但它可以用於其他客戶端-服務器軟件項目。

官方地址:https://redis.io/topics/protocol

RESP特點如下:
易於實現
快速解析
可讀性高
網絡傳輸(基於TCP)

客戶端連接到Redis服務器,以創建與端口6379的TCP連接。儘管RESP在技術上不是特定於TCP的,但在Redis的上下文中,該協議僅與TCP連接(或等效的面向流的連接,如Unix套接字)一起使用。

請求-響應模型

Redis接受由不同參數組成的命令。收到命令後,將對其進行處理並將答覆發送回客戶端。

這是最簡單的模型,但是有兩個例外:

  1. 管道化技術
    Redis支持流水線化(在本文檔後面介紹)。因此,客戶端可以一次發送多個命令,並在以後等待答覆。
  2. 發佈/訂閱模型
    當Redis客戶端訂閱Pub / Sub通道時,該協議會更改語義併成爲推送協議,也就是說,客戶端不再需要發送命令,因爲服務器會自動向客戶端發送新消息(對於客戶端的通道訂閱)。
    除了上述兩個例外,Redis協議是一種簡單的請求-響應協議。
    在這裏插入圖片描述
RESP數據類型:

RESP可以序列化不同的數據類型,例如整數簡單字符串數組錯誤類型大字符串。請求以字符串數組的形式從客戶端發送到Redis服務器,這些字符串表示要執行的命令的參數。Redis使用特定於命令的數據類型進行回覆。

  1. 對於簡單字符串,答覆的第一個字節爲“ +”
  2. 對於錯誤,回覆的第一個字節爲“-”
  3. 對於整數,答覆的第一個字節爲“:”
  4. 對於大字符串,答覆的第一個字節爲“ $”
  5. 對於數組,回覆的第一個字節爲“ *”
1. RESP簡單字符串:

簡單字符串的編碼方式如下:一個加號,後跟一個不能包含CR或LF字符的字符串(不允許換行),以CRLF終止(即“ \ r \ n”)。

簡單字符串用於以最小的開銷傳輸非二進制安全字符串。例如,許多Redis命令在成功後僅回答“ OK”,這是作爲RESP簡單字符串編碼的以下5個字節:

"+OK\r\n"

爲了發送二進制安全的字符串,請使用RESP批量字符串

當Redis用簡單字符串答覆時,客戶端庫應向調用者返回一個字符串,該字符串由’+'之後的直到字符串末尾的第一個字符組成,不包括最後的CRLF字節

2. RESP錯誤

RESP具有用於錯誤的特定數據類型。實際上,錯誤與RESP簡單字符串完全一樣,但是第一個字符是減號“-”而不是加號。RESP中的簡單字符串和錯誤之間的真正區別是,客戶端將錯誤視爲異常,而組成錯誤類型的字符串是錯誤消息本身。
基本格式爲:

"-Error message\r\n"

僅當發生錯誤時才發送錯誤答覆,例如,如果您嘗試對錯誤的數據類型執行操作,或者命令不存在等等。收到錯誤回覆時,庫客戶端應引發異常。

以下是錯誤回覆的示例:

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

“-”之後的第一個單詞,直到第一個空格或換行符,代表返回的錯誤類型。這只是Redis使用的約定,不是RESP錯誤格式的一部分。

3. RESP整數

此類型只是一個CRLF終止的字符串,它表示一個整數,以“:”字節爲前綴。例如,“:0 \ r \ n”或“:1000 \ r \ n”是整數回覆。

:0\r\n

許多Redis命令返回RESP整數,像INCR,LLEN和LASTSAVE。

返回的整數沒有特殊含義,它只是INCR的增量數,LASTSAVE的UNIX時間等等。但是,保證返回的整數在帶符號的64位整數範圍內。爲了返回true或false,還廣泛使用Integer答覆。例如,像EXISTS或SISMEMBER這樣的命令將爲true返回1,爲false返回0。

4. RESP大容量字符串

使用大容量字符串來表示單個最大長度爲512 MB二進制安全字符串。

大容量字符串以以下方式編碼:
“ $”字節,後跟組成字符串的字節數(帶前綴的長度),由CRLF終止。實際的字符串數據。最後的CRLF。
因此,字符串“ foobar”的編碼如下:

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

空字符串:

"$0\r\n\r\n"

還可以使用RESP散裝字符串,以使用用於表示Null值的特殊格式來表示值的不存在。在這種特殊格式中,長度爲-1,並且沒有數據,因此Null表示爲:

"$-1\r\n"
5. RESP數組

客戶端使用RESP數組將命令發送到Redis服務器。類似地,某些Redis命令將元素集合返回給客戶端使用RESP數組是回覆類型。一個示例是返回列表元素的LRANGE命令。

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

一個*字符作爲第一個字節,然後是數組中的元素數(作爲十進制數),然後是CRLF。
數組中每個元素的附加RESP類型。
因此,空數組只是以下內容:

"*0\r\n"

兩個RESP散列字符串“ foo”和“ bar”的數組編碼爲:

"*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n"

三個整數的數組編碼如下:

"*3\r\n:1\r\n:2\r\n:3\r\n"

數組可以包含混合類型,元素不必是同一類型。例如,可以將四個整數和一個大容量字符串的列表編碼如下:

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

當BLPOP命令超時時,它將返回一個Null Array,其計數爲-1,空數組:

"*-1\r\n"

在RESP中可以使用數組的數組。例如,兩個數組的數組編碼如下:

*2\r\n
*3\r\n
:1\r\n
:2\r\n
:3\r\n
*2\r\n
+Foo\r\n
-Bar\r\n

將命令發送到Redis服務器

既然您已經熟悉了RESP序列化格式,那麼編寫Redis客戶端庫的實現將變得很容易。我們可以進一步指定客戶端和服務器之間的交互方式:

客戶端向Redis服務器發送僅由批量字符串組成的RESP數組
Redis服務器會回覆發送任何有效RESP數據類型作爲回覆的客戶端。

客戶端發送命令LLEN mylist來獲取存儲在密鑰mylist上的列表的長度,服務器將以Integer答覆進行答覆,如以下示例所示(C:是客戶機,S:服務器)。

C: *2\r\n
C: $4\r\n
C: LLEN\r\n
C: $6\r\n
C: mylist\r\n

S: :48293\r\n
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章