1. 程式人生 > >redis通訊協議學習

redis通訊協議學習

Redis 的作者認為資料庫系統的瓶頸一般不在於網路流量,而是資料庫自身內部邏輯處理上。所以即使 Redis 使用了浪費流量的文字協議,依然可以取得極高的訪問效能。Redis 將所有資料都放在記憶體,用一個單執行緒對外提供服務,單個節點在跑滿一個 CPU 核心的情況下可以達到了 10w/s 的超高 QPS。

RESP(Redis Serialization Protocol)

RESP 是 Redis 序列化協議的簡寫。它是一種直觀的文字協議,優勢在於實現異常簡單,解析效能極好。

Redis 協議將傳輸的結構資料分為 5 種最小單元型別,單元結束時統一加上回車換行符號\r\n。

1.單行字串 以 + 符號開頭。

2.多行字串 以 $ 符號開頭,後跟字串長度。

3.整數值 以 : 符號開頭,後跟整數的字串形式。

4.錯誤訊息 以 - 符號開頭。

5.陣列 以 * 號開頭,後跟陣列的長度。

單行字串 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\r\n

陣列 [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 指令set author codehole會被序列化成下面的字串。

*3\r\n$3\r\nset\r\n$6\r\nauthor\r\n$8\r\ncodehole\r\n

在控制檯輸出這個字串如下,可以看出這是很好閱讀的一種格式。

*3
$3
set
$6
author
$8
codehole

伺服器 -> 客戶端

伺服器向客戶端回覆的響應要支援多種資料結構,所以訊息響應在結構上要複雜不少。不過再複雜的響應訊息也是以上 5 中基本型別的組合。

單行字串響應

127.0.0.1:6379> set author codehole
OK

這裡的 OK 就是單行響應,沒有使用引號括起來。

+OK

錯誤響應

127.0.0.1:6379> incr author
(error) ERR value is not an integer or out of range

試圖對一個字串進行自增,伺服器丟擲一個通用的錯誤。

-ERR value is not an integer or out of range

整數響應

127.0.0.1:6379> incr books
(integer) 1

這裡的1就是整數響應

:1

多行字串響應

127.0.0.1:6379> get author
"codehole"

這裡使用雙引號括起來的字串就是多行字串響應

$8
codehole

陣列響應

127.0.0.1:6379> hset info name laoqian
(integer) 1
127.0.0.1:6379> hset info age 30
(integer) 1
127.0.0.1:6379> hset info sex male
(integer) 1
127.0.0.1:6379> hgetall info
1) "name"
2) "laoqian"
3) "age"
4) "30"
5) "sex"
6) "male"

這裡的 hgetall 命令返回的就是一個數組,第 0|2|4 位置的字串是 hash 表的 key,第 1|3|5 位置的字串是 value,客戶端負責將陣列組裝成字典再返回。

*6
$4
name
$6
laoqian
$3
age
$2
30
$3
sex
$4
male

巢狀

127.0.0.1:6379> scan 0
1) "0"
2) 1) "info"
   2) "books"
   3) "author"

scan 命令用來掃描伺服器包含的所有 key 列表,它是以遊標的形式獲取,一次只獲取一部分。

scan 命令返回的是一個巢狀陣列。陣列的第一個值表示遊標的值,如果這個值為零,說明已經遍歷完畢。如果不為零,使用這個值作為 scan 命令的引數進行下一次遍歷。陣列的第二個值又是一個數組,這個陣列就是 key 列表。

*2
$1
0
*3
$4
info
$5
books
$6
author

小結

Redis 協議裡有大量冗餘的回車換行符,但是這不影響它成為網際網路技術領域非常受歡迎的一個文字協議。有很多開源專案使用 RESP 作為它的通訊協議。在技術領域效能並不總是一切,還有簡單性、易理解性和易實現性,這些都需要進行適當權衡。