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种数据使用场景

搞懂Redis协议RESP的更多相关文章

  1. 真正“搞”懂HTTP协议02之空间穿梭

    时隔四年,这个系列鸽了四年,我终于觉得我可以按照自己的思路和想法把这个系列完整的表达出来了. 想起四年前,那时候还是2018年的六月份,那时候我还工作不到两年,那时候我翻译了RFC2616的部分内容, ...

  2. 真正“搞”懂http协议01—背景故事

    去年读了<图解HTTP>.<图解TCP/IP>以及<图解网络硬件>但是读了之后并没有什么深刻的印象,只是有了一层模糊的脉络,刚好最近又接触了一些有关http的相关内 ...

  3. 真正“搞”懂HTTP协议03之时间穿梭

    上一篇我们简单的介绍了一下DoD模型和OSI模型,还着重的讲解了TCP的三次握手和四次挥手,让我们在空间层面,稍稍宏观的了解了HTTP所依赖的底层模型,那么这一篇,我们来追溯一下HTTP的历史,看一看 ...

  4. 彻底搞懂Redis主从复制原理及实战

    欢迎关注公众号:「码农富哥」,致力于分享后端技术 (高并发架构,分布式集群系统,消息队列中间件,网络,微服务,Linux, TCP/IP, HTTP, MySQL, Redis), Python 等 ...

  5. 【干货!!】三句话搞懂 Redis 缓存穿透、击穿、雪崩

    前言 如何有效的理解并且区分 Reids 穿透.击穿和雪崩之间的区别,一直以来都挺困扰我的.特别是穿透和击穿,过一段时间就稀里糊涂的分不清了. 为了有效的帮助笔者自己,以及拥有同样烦恼的朋友们区分这三 ...

  6. 从网络通信的演进过程彻底搞懂Redis高性能通信的原理(全网最详细,建议收藏)

    我们一直说Redis的性能很快,那为什么快?Redis为了达到性能最大化,做了哪些方面的优化呢? 在深度解析Redis的数据结构 这篇文章中,其实从数据结构上分析了Redis性能高的一方面原因. 在目 ...

  7. 搞懂Redis RDB和AOF持久化及工作原理

    前言 因为Redis的数据都储存在内存中,当进程退出时,所有数据都将丢失.为了保证数据安全,Redis支持RDB和AOF两种持久化机制有效避免数据丢失问题.RDB可以看作在某一时刻Redis的快照(s ...

  8. 搞懂Redis到底快在哪里

    前言 Redis是一种基于键值对(Key-Value)的NoSQL数据库,Redis的Value可以由String,hash,list,set,zset,Bitmaps,HyperLogLog等多种数 ...

  9. 一文轻松搞懂redis集群原理及搭建与使用

    今天早上由于zookeeper和redis集群不在同一虚拟机导致出了点很小错误(人为),所以这里总结一下redis集群的搭建以便日后所需同时也希望能对你有所帮助. 笔主这里使用的是Centos7.如果 ...

随机推荐

  1. Java-数组有关

    1.复制数组 复制数组主要有三类方法: 1.使用循环语句逐个赋值数组元素 2.使用System类中的静态方法arraycopy 3.使用clone方法复制数组 对于2,详述如下: arraycopy( ...

  2. 理解 React Hooks 心智模型:必须按顺序、不能在条件语句中调用的规则

    前言 自从 React 推出 hooks 的 API 后,相信大家对新 API 都很喜欢,但是它对你如何使用它会有一些奇怪的限制.比如,React 官网介绍了 Hooks 的这样一个限制: 不要在循环 ...

  3. java高级编程笔记(四)

    java的Object类: 1.Object 类位于 java.lang 包中,编译时会自动导入:Java 的所有类都继承了 Object,子类可以使用 Object 的所有方法. 2.Object ...

  4. C++第五十篇 -- 获取串口的描述信息

    如何知道自己的电脑上有无串口呢? -- 手动 1. 查看电脑,看是否有串口器件(串口是一个九针的D型接口) 2. 在设备管理器上查看 乍一看,还以为是有两个串口,其实仔细看描述就知道,这是蓝牙虚拟串口 ...

  5. QLabel的使用

    现在学习一个简单的控件Label. 第一步:打开designer.exe.拖动一个控件到主窗口,双击可以编辑文字. 第二步:设置字体大小 第三步:设置文字颜色 第四步:设置背景色 第五步:将文字居中 ...

  6. Jenkins远程命令执行漏洞(CVE-2018-1000861)

    此漏洞没有回显,直接利用orange的exp执行命令反弹shell 工具地址https://github.com/orangetw/awesome-jenkins-rce-2019 web服务器下写1 ...

  7. C++手写内存池

    引言 使用new expression为类的多个实例分配动态内存时,cookie导致内存利用率可能不高,此时我们通过实现类的内存池来降低overhead.从不成熟到巧妙优化的内存池,得益于union的 ...

  8. 浅谈vue响应式原理及发布订阅模式和观察者模式

    一.Vue响应式原理 首先要了解几个概念: 数据响应式:数据模型仅仅是普通的Javascript对象,而我们修改数据时,视图会进行更新,避免了繁琐的DOM操作,提高开发效率. 双向绑定:数据改变,视图 ...

  9. vue日记②之兼容各种情况的可跳转链接

    兼容各种情况的可跳转链接 需求 因为聊天气泡颜色原因,发送出去的链接通常模糊不清,而且不能直接跳转,所以我打算已a链接的显示直接抓取所有的网页链接,同时还要兼容富文本框的直接输入图片 这是运行效果 实 ...

  10. 2021字节跳动校招秋招算法面试真题解题报告--leetcode206 反转链表,内含7种语言答案

    206.反转链表 1.题目描述 反转一个单链表. 示例: 输入: 1->2->3->4->5->NULL输出: 5->4->3->2->1-> ...