Redis的作者認爲數據庫系統的瓶頸一般不在於網絡流量,而是數據庫自身內部邏輯處理上。所以即使Redis使用了浪費流量的文本協議,依然可以取得極高的訪問性能。Redis將所有數據都放在內存,用一個單線程對外提供服務,單個節點在跑滿一個CPU核心的情況下可以達到了10w/s的超高QPS。
RESP(Redis Serialization Protocol)
RESP是Redis序列化協議的簡寫。它是一種直觀的文本協議,優勢在於實現異常簡單,解析性能極好。Redis協議將傳輸的結構數據分爲5種最小單元類型,單元結束時統一加上回車換行符號\r\n。
-
單行字符串 以 + 符號開頭。
-
多行字符串 以 $ 符號開頭,後跟字符串長度。
-
整數值 以 : 符號開頭,後跟整數的字符串形式。
-
錯誤消息 以 - 符號開頭。
-
數組 以 * 號開頭,後跟數組的長度。
單行字符串
#單行字符串hello world
+hello world\r\n
多行字符串
#多行字符串 hello world 。多行字符串當然也可以表示單行字符串。
$11\r\nhello world\r\n
整數
#整數 1024
:1024\r\n
錯誤消息
#錯誤參數類型錯誤
-WRONGTYPE Operation against a key holding the wrong kind of value
數組
#數組 [1,2,3]
*3\r\n:1\r\n:2\r\n:3\r\n
注意點:
NULL:用多行字符串表示,不過長度要寫成-1。
$-1\r\n
空串:用多行字符串表示,長度填0。
$0\r\n\r\n
注意這裏有兩個\r\n。爲什麼是兩個? 因爲兩個\r\n之間隔的是空串。
客戶端請求指令
客戶端向服務器發送的指令只有一種格式,多行字符串數組。
例如:
>set name mango
#指令轉換
*3\r\n$3\r\nset\r\n$4\r\name\r\n$5\r\mango\r\n
#在控制檯輸出這個字符串
*3
$3
set
$4
name
$5
mango
服務器響應結果
服務器向客戶端回覆的響應要支持多種數據結構,所以消息響應在結構上要複雜不少。不過再複雜的響應消息也是以上 5 種基本類型的組合。
單行字符串響應
> set name mango
OK
#響應消息
+OK
錯誤響應
> incr name
(error) ERR value is not an integer or out of range
#響應消息
-ERR value is not an integer or out of range
整數類型響應
> incr number
(integer) 1
#響應消息
:1
多行字符串響應
> get name
"mango"
#響應消息 這裏使用雙引號括起來的字符串就是多行字符串響應
$5
mango
數組響應
> hset user name mango
(integer) 1
> hset user age 18
(integer) 1
> hgetall user
1) "name"
2) "mango"
3) "age"
4) "18"
#響應信息
*4
$4
name
$5
mango
$3
age
$2
18
嵌套
> scan 0 match name* count 10
1) "0"
2) 1) "name1"
2) "name2"
#響應信息
*2
$1
0
*2
$5
name1
$5
name2
Redis協議裏有大量冗餘的回車換行符,但是這不影響它成爲互聯網技術領域非常受歡迎的一個文本協議。有很多開源項目使用RESP作爲它的通訊協議。在技術領域性能並不總是一切,還有簡單性、易理解性和易實現性,這些都需要進行適當權衡。
一名正在搶救的coder
筆名:mangolove
CSDN地址:https://blog.csdn.net/mango_love
GitHub地址:https://github.com/mangoloveYu