[转帖]一文带你玩转 Redis 的 RESP 协议 !

一文,玩转,redis,resp,协议 · 浏览次数 : 0

小编点评

## Redis 客户端与服务器之间的通信协议 **全称:**Redis Serialization Protocol (REdis Serialization Protocol) **简单易懂:**它是一种应用层协议,即它的底层还是依赖于 TCP/IP RESP 的设计哲学。 **结构:** * 请求报文格式:*3CRLF$参数数量$参数1的数据$... * 响应报文格式:+开头, followed by 参数数量, then 参数数据。 **常用指令格式:** * `set key1 value1` : 将键值对设置到 key1 中。 * `get key1` : 从 key1 中获取值。 **一些简单的响应报文:** * `+OKCRLF` : 表示设置成功。 * `-ERR unknown command` : 表示发送错误指令时。 * `$6CRLF value1CRLF` : 批量回复多个值。 * `$-1CRLF` : 表示获取指定键值不存在。 * `*2$3123$6123456` : 获取 key2 的所有值。

正文

 

RESP 是 Redis 客户端与 Redis 服务器相互通信时使用的一个协议, 全称 REdis Serialization Protocol ,即 redis 串行协议,通俗易懂,也表明了 redis 的特点,串行化(单线程)

注意: RESP 协议是一个应用层协议,也就是说它的底层还是依赖于 tcp/ip

RESP 的设计哲学

Redis 的作者在设计 RESP 协议,制定了下面的三条原则:

  1. 实现要简单
  2. 对计算机来说,解析速度快
  3. 对人类来说,可读性强

请求报文格式

Redis 客户端请求服务器时,报文格式非常简单,模板如下(注意:这里为了方便查看,CRLF 后面我还进行了手动换行,实际上是没有的)

*<参数数量>CRLF
$<参数1的字节长度>CRLF
<参数1的数据>CRLF
...
$<参数N的字节长度>CRLF
<参数N的数据>CRLF

其实就3个要素,参数的总个数,参数的字节长度、参数数据

例如,启动 redis-cli 客户端,发送一条命令:

set key1 value1 

则这条命令对应的 RESP 协议报文内容为

*3CRLF$3CRLFsetCRLF$4CRLFkey1CRLF$6CRLFvalue1 

为了方便我们人类查看,我将 CRLF 控制字符打印出来

*3
$3
set
$4
key1
$6
value1

附上注释

*3 //* 表示报文的开始,3 表示有三个参数,分别是 set、key1、value1
$3 // $3 表示第一个参数长度为 3 个字节
set  // 一个参数
$4 // 第二个参数长度为 4 个字节
key1 // 第二个参数
$6 // 第三个参数长度为 6 个字节
value1 // 第三个参数

客户端请求报文就是这么简单

响应报文格式

请求报文的格式只有一种,但响应报文的格式就多种多样了

简单字符串回复

简单字符串回复只有一行回复,回复的内容以 + 作为开头,不允许换行,并以 \r\n 结束。有很多指令在执行成功后只会回复一个 OK,使用的就是这种格式,能够有效的将传输、解析的开销降到最低。

例如上面的

set key1 value1 

假设执行成功,返回报文为

+OKCRLF 

错误回复

在 RESP 协议中,错误回复相当于简单字符串回复的变种形式,它们之间的格式也非常类似,区别只有第一个字符是以 - 作为开头,错误回复的内容通常是错误类型及对错误描述的字符串。

错误回复出现在一些异常的场景,例如当发送了错误的指令、操作数的数量不对时,都会进行错误回复。在客户端收到错误回复后,会将它视为异常。

例如

set1 key1 value1 

由于没有 set1 这个命令,所以返回错误报文

-ERR unknown command `set1`, with args beginning with: `key1`, `value`,CRLF 

整数回复

整数回复的报文非常简单

:数字CRLF 

一般出现在用户执行 exists、 incr、llen 等返回结果是数值或布尔类型的命令时,例如

exists key1 

的回复报文为

:1CRLF 

批量回复

批量回复的报文,模板如下

$<内容长度>CRLF
<内容>CRLF

它以 $ 作为开头,后面是发送的字节长度,然后是 CRLF,然后发送实际的数据,最终以 CRLF 结束。如果没有要回复的信息,那么回复长度为 -1。

举例

get key1 

的回复报文为

$6CRLF value1CRLF 
get key2 

的回复报文为

$-1CRLF 

多条批量回复

多条批量回复的报文与客户端请求报文一模一样

*<参数数量>CRLF
$<参数1的字节长度>CRLF
<参数1的数据>CRLF
...
$<参数N的字节长度>CRLF
<参数N的数据>CRLF

多见于获取 hash、set、list 等类型的相关数据时,例如

lrange key2 0 -1 

的回复报文为

*2
$3
123
$6
123456

与[转帖]一文带你玩转 Redis 的 RESP 协议 !相似的内容:

[转帖]一文带你玩转 Redis 的 RESP 协议 !

https://zhuanlan.zhihu.com/p/384251739 RESP 是 Redis 客户端与 Redis 服务器相互通信时使用的一个协议, 全称 REdis Serialization Protocol ,即 redis 串行协议,通俗易懂,也表明了 redis 的特点,串行化(

[转帖]一文带你掌握 Redis

https://www.bbsmax.com/A/8Bz8AKGkJx/ 一、摘要 谈起 Redis,相信大家都不会陌生,做过云平台开发的程序员多多少少会接触到它,Redis 英文全称:Remote Dictionary Server,也被称之为远程字典服务。 从官方的定义看,Redis 是一款开源

[转帖]一文带你搞懂 CDN 的技术原理

http://blog.itpub.net/31545813/viewspace-2924432/ 网络通信/物联网 编辑:李雪薇 时间:2022-11-22 09:11:41 1330 0 CDN 的全称是 Content Delivery Network,即内容分发网络。其目的是通过在现有的In

[转帖]一文带你搞懂xxl-job(分布式任务调度平台)

https://zhuanlan.zhihu.com/p/625060354 前言 本篇文章主要记录项目中遇到的 xxl-job 的实战,希望能通过这篇文章告诉读者们什么是 xxl-job 以及怎么使用 xxl-job 并分享一个实战案例。 那么下面先说明什么是 xxl-job 以及为什么要使用它。

[转帖]一文带你了解mysql sql model的only_full_group_by模式

https://zhuanlan.zhihu.com/p/368440685 Mysql only_full_group_by与Error 1055问题分析 1 声明 本文的数据来自网络,部分代码也有所参照,这里做了注释和延伸,旨在技术交流,如有冒犯之处请联系博主及时处理。 2 问题描述 ERROR

[转帖]一文了解 Java 中的构造器

https://my.oschina.net/u/4526289/blog/5577621 摘要:Java 也采用了构造器,并且还提供了一个垃圾收集器(garbage collector),当不再使用内存资源的时候,垃圾收集器会自动将其释放。 本文分享自华为云社区《一文带你了解 Java 中的构造器

[转帖]一代更比一代强!一文带你回顾DDR内存的前世今生

根据冯诺·依曼结构,计算机中要有存储器。所以直到今天,内存和硬盘仍然在电脑中占有非常重要的地位。与大容量的硬盘不同,内存在存取速度上有着非常惊人的表现,但是断电后又不能保存存入的信息。因此在电脑硬件长期的发展过程中,内存一直扮演着中转站的角色。和其他硬件一样,内存遵循着摩根定律,从最远古的SIMM到

[转帖]shell脚本之awk命令——按列求平均值、最大值、最小值

文章目录 写在前面awk求平均值awk求最大值awk求最小值awk求极值、均值的实际应用 写在前面 awk命令求极值和均值需要熟悉该命令的基本用法,如果你不熟悉该命令,请先阅读shell脚本之awk命令——分隔符介绍一文。本篇博文带你熟悉求平均值、最大值、最小值的方法,并以实际的应用带你进一步掌握a

[转帖]万字详解 JVM,让你一文吃透

https://my.oschina.net/u/4526289/blog/5588880 摘要:本文将带大家详细地了解关于 JVM 的一些知识点。 本文分享自华为云社区《【JVM】关于 JVM,你需要掌握这些 | 一文彻底吃透 JVM 系列》,作者: 冰 河 。 JDK 是什么? JDK 是用于支

[转帖]一文搞懂不同方式Redis集群搭建

https://bbs.huaweicloud.com/blogs/380521 【摘要】 1 实验环境准备 1.1 构建Redis的Docker镜像[root@iZ2ze4m2ri7irkf6h6n8zoZ redis]# docker pull redis[root@iZ2ze4m2ri7irk