Redis協議規範
Redis客戶端使用稱爲RESP(REdis序列化協議)的協議與Redis 服務器進行通信。雖然該協議是專爲Redis設計的,但它可以用於其他客戶端-服務器軟件項目。
官方地址:https://redis.io/topics/protocol
RESP特點如下:
易於實現 |
---|
快速解析 |
可讀性高 |
網絡傳輸(基於TCP)
客戶端連接到Redis服務器,以創建與端口6379的TCP連接。儘管RESP在技術上不是特定於TCP的,但在Redis的上下文中,該協議僅與TCP連接(或等效的面向流的連接,如Unix套接字)一起使用。
請求-響應模型
Redis接受由不同參數組成的命令。收到命令後,將對其進行處理並將答覆發送回客戶端。
這是最簡單的模型,但是有兩個例外:
- 管道化技術
Redis支持流水線化(在本文檔後面介紹)。因此,客戶端可以一次發送多個命令,並在以後等待答覆。 - 發佈/訂閱模型
當Redis客戶端訂閱Pub / Sub通道時,該協議會更改語義併成爲推送協議,也就是說,客戶端不再需要發送命令,因爲服務器會自動向客戶端發送新消息(對於客戶端的通道訂閱)。
除了上述兩個例外,Redis協議是一種簡單的請求-響應協議。
RESP數據類型:
RESP可以序列化不同的數據類型,例如整數,簡單字符串,數組、錯誤類型、大字符串。請求以字符串數組的形式從客戶端發送到Redis服務器,這些字符串表示要執行的命令的參數。Redis使用特定於命令的數據類型進行回覆。
- 對於簡單字符串,答覆的第一個字節爲“ +”
- 對於錯誤,回覆的第一個字節爲“-”
- 對於整數,答覆的第一個字節爲“:”
- 對於大字符串,答覆的第一個字節爲“ $”
- 對於數組,回覆的第一個字節爲“ *”
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