搞懂Redis協議RESP


RESP (REdis Serialization Protocal)

Redis客戶端和服務端之間通信的協議。它很簡單,建立在TCP協議上,提供簡單、高性能、可讀性強的數據序列化的規范和語義。

5種數據模型

  • Simple Strings
  • Errors
  • Integers
  • Bulk Strings
  • Array

Simple Strings

Simple Strings用於服務端對一些客戶端命令的響應

格式:"+"開頭 "\r\n"結尾,中間內容不能含有'\r'或'\n'

# set命令得到響應
127.0.0.1:6379> set name Foo
OK
# 服務端返回完整內容:"+OK\r\n“

# 退出命令
127.0.0.1:6379> quit

# 服務端返回的完整內容:+OK\r\n

Simple Strings的結構是非常簡單的,而且不是二進制安全的;所以只會在服務端的簡單內容返回。只是GETMGET等命令的內容返回會用Buik Strings。

Errors

Errors 用於服務端對客戶端一些錯誤命令的返回內容

格式:"-"開頭 "\r\n"結尾

# 執行不存在的命令
127.0.0.1:6379> gee name
(error) ERR unknown command 'gee'
# 服務端返回完整內容:"-ERR unknown command 'gee'\r\n"

# 錯誤的類型操作
127.0.0.1:6379> set name Bob
OK
127.0.0.1:6379> zadd name 1 Foo
(error) WRONGTYPE Operation against a key holding the wrong kind of value
# 服務端返回完成內容:"-WRONGTYPE Operation against a key holding the wrong kind of value\r\n"

從例子中可以看出Erorrs響應中間部分的內容由兩部分構成:大寫代表錯誤類型,消息的表示錯誤詳情。即-Error message\r\n

Integers

用於需要返回整數內容的命令,比如:INCRLLEN

格式:":"開頭,\r\n結尾,中間部分必須是有效的整數

# incr
127.0.0.1:6379> set count 1
OK
127.0.0.1:6379> incr count
(integer) 2
# 服務端返回完整內容:":2\r\n"

# lpush llen del
127.0.0.1:6379> lpush userList Bob
(integer) 1
127.0.0.1:6379> llen userList
(integer) 1
# 服務端返回完整內容:":1\r\n",代表列表中當前元素書,數量

# del
127.0.0.1:6379> del userList
(integer) 1
# 服務端返回完整內容:":1\r\n", 含義是執行成功

# exists
127.0.0.1:6379> set name Bob
OK
127.0.0.1:6379> exists name2
(integer) 0
# 服務端返回完整內容:":0\r\n",含義是不存在
127.0.0.1:6379> exists name
(integer) 1
# 服務端返回完整內容:":1\r\n",含義是存在

這些命令的響應內容都是使用Integers:SETNX, DEL, EXISTS, INCR, INCRBY, DECR, DECRBY, DBSIZE, LASTSAVE, RENAMENX, MOVE, LLEN, SADD, SREM, SISMEMBER, SCARD

Bulk Strings

用來傳輸二進制安全的字符內容,最大長度是512MB

格式:'$'開頭,后跟整數代表真正字符長度,然后\r\n,后面接真正的字符串內容,最后\r\n結尾,例:"$6\r\nfoobar\r\n"

正常返回

127.0.0.1:6379> set name foo
OK
127.0.0.1:6379> get name
"foo"
# 服務端返回完整內容:"$3\r\nfoo\r\n"

空字符串返回

127.0.0.1:6379> set name ""
OK
127.0.0.1:6379> get name
""
# 服務端返回完整內容:"$0\r\n\r\n"

null返回,即get不存在的key

127.0.0.1:6379> del name
(integer) 1
127.0.0.1:6379> get name
(nil)
# 服務端返回完整內容:"$-1\r\n"

當服務器返回Null Bulk Strings時,客戶端庫應該轉換為Null對象返回,而不要返回空字符。空字符串和nil是兩個含義,空字符串代表鍵的值為'',nil代表鍵不存在

Arrays

用作客戶端向服務端發送命令時的內容格式,也用於服務端對一些命令的內容格式,如:LRANGE

格式:"*"開頭,后跟整數表示數組長度,然后\r\n,后面是數組中的每個元素,他們可以是任意RESP類型(上面提到的Intergers、Bulk String等,格式如上),他們之間用\r\n分割,結尾\r\n

來看看set name Foo這條命令,client是怎么傳給server的

127.0.0.1:6379> set name Foo
OK
# 客戶端發的完整內容"*3\r\n$3\r\nset\r\n$4\r\nname\r\n$3\r\nFoo\r\n"
  • *3 代表這個內容是Arrays類型,並且長度為3,因為set name Foo有3個字符串
  • \r\n 分割符
  • $3 第一個字符串長度為3
  • \r\n 分割符
  • set 具體內容set
  • \r\n 分割符
  • $4 第二個字符串長度為4
  • name 具體內容name
  • \r\n 分割符
  • $3 第三個字符串長度為3
  • \r\n 分割符
  • Foo 具體內容Foo
  • \r\n 結尾

接着看看mget name name1這條命令發出后,server返回的內容

127.0.0.1:6379> mget name name2
1) "Foo"
2) (nil)
# 服務端返回完成內容:*2\r\n$3\r\nFoo\r\n$-1\r\n"
  • *2 代表這個內容是Arrays類型,並且長度為2,因為我們查了兩個鍵namename2
  • \r\n
  • $3 第一個字符串長度為3
  • \r\n
  • Foo 具體內容Foo,即剛才set name Foo命令生效結果
  • \r\n
  • $-1 第二個字符串長度為-1,表示nil,不存在
  • \r\n

null數組表示

127.0.0.1:6379> blpop foo 1
(nil)
# 服務端返回完成內容: "*-1\r\n"

同樣,客戶端庫也要區別null數組和空數組的區別。

總結

RESP協議的5種數據使用場景


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM