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的結構是非常簡單的,而且不是二進制安全的;所以只會在服務端的簡單內容返回。只是GET、MGET等命令的內容返回會用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
用於需要返回整數內容的命令,比如:INCR、LLEN等
格式:":"開頭,\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第二個字符串長度為4name具體內容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,因為我們查了兩個鍵name和name2\r\n$3第一個字符串長度為3\r\nFoo具體內容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種數據使用場景

