Redis客户端通过使用一种叫RESP(REdis Serialization Protocol, redis序列化协议)协议与Redis服务器交互。虽然这个协议是为Redis而设计的,但它也可以用于其他client-server架构的软件系统。(译注: 从一些公开的资料来看,陌陌的IM协议设计就参考了Redis协议)
RESP 权衡了以下几个方面:
实现要简单解析要快方便人阅读
RESP可以序列化不同的数据类型,像integers、strings、arrays,对于错误也设计了特殊的类型。客户端以字符串参数数组的请求形式发送给Redis服务器执行,Redis返回命令相关的数据类型。
RESP是二进制安全(binary-safe)的,并且不需要解析由一个进程发送给另一个进程的bulk 数据,因为它使用长度前缀来传输bulk 数据。
注意:这里所说的协议只用于client-server的通信。Redis Cluster使用不同的二进制协议在node间进行消息交互。
网络层
客户端通过建立端口为6379的TCP连接与Redis通信。
虽然RESP从技术上来说并不是TCP相关的,但对Redis来说该协议只用于TCP(或者其他流式协议如Unix域协议)。 (译注:反观memcached, 既支持tcp, 也支持udp, 但实际上生产环境基本只用tcp。我认为这是一种过度设计了,搞不好还可能被骇客利用来做 memcached udp 反射攻击。。。)
请求响应模型
Redis 接收不同参数构成的命令。当命令接收到后就会被处理,然后响应发送给客户端。
这是最简单的模型了,但有两点例外:
Redis支持 pipelining (后文会提及)。所以客户端可以一次发送多个命令,然后等待响应。当客户端订阅了一个 Pub/Sub channel, 该协议会改变语意而变成一个推送协议,也就是说客户端不用发送命令,因为服务端在收到消息后会自动给客户端发送新的消息(对客户端订阅了的channel)。
除了这两点,Redis协议就是一个简单的请求-响应协议。
RESP协议描述
RESP协议在Redis 1.2引入,但它现在成为Redis 2.0的标准交互协议。你应该实现Redis客户端时采用该协议。
RESP事实上是一个支持以下类型的序列化协议:Simple Strings, Errors, Integers, Bulk Strings 和 Arrays。
RESP作为一种请求响应协议,在Redis中使用的方式如下:
客户端发送命令到Redis服务器,以RESP Bulk Strings数组的方式。服务器根据不同的命令实现,返回相应的RESP实现。
在RESP中,一些数据的类型由第一个字节确定:
对于SImple Strings 响应的第一个字节是“+”对于Errors 响应的第一个字节是 "-"对于Integers 响应第一个字节是 ":"对于Bulk Strings 响应第一个字节是 "$" 对于Arrays 响应第一个字节是 "*"
另外RESP可以用特殊的Bulk String或数组来表示 Null 值,后文会提及。
在RESP中协议不同部分总是用 "\r\n" (CRLF) 分隔。
RESP Simple Strings
Simple Strings通过以下方式编码:一个加号,后跟一个字符串, 字符串不包含CR或LF字符(不能有换行),以CRLF ("\r\n")结束。
SImple Strings 以最小的代价来传输非二进制安全的字符串。例如很多Redis命令在成功时响应"OK",就是用RESP Simple String 来编码的5个字节:
"+OK\r\n"
为了传输二进制安全的字符串,要用RESP Bulk Strings。
当Redis响应一个Simple String时,客户端库应该给调用者返回从第一个"+"字符到字符串结尾的字符串,不包括CRLF 字节。
RESP Errors
RESP 对于error有一种特殊的数据类型。实际上error就像RESP Simple String一样,但第一个字符串是"-"而不是加号。在RESP中 Simple Strings和Errors两者的真正区别在于errors被客户端作为异常,构成Error类型的字符串就是字符串本身。基本格式是:
"-Error message\r\n"
Error响应只会在有错误发生时才会发送,例如你操作了错误的数据类型,或者命令不存在等。当收到Error响应时,客户端应该抛出一个异常。
以下是error响应的例子:
-ERR unknown command 'foobar'-WRONGTYPE Operation against a key holding the wrong kind of value
在"-"到第一个空格或新行间的第一个词,表示返回的错误类型。这只是Redis自己的一种约定,并不是RESP Error 所规定的格式。
例如,ERR 是通用错误,而 WRONGTYPE 是一种更加具体的错误,表示客户端尝试操作错误的数据类型。这称为 Error Prefix (Error前缀),客户端可从此得知服务器返回错误的类型而不需依赖于那个确切的消息描述,后者会随时改变。
一个客户端的实现可能对不同的error返回不同类型的异常,或者向调用者返回代表错误的字符串。然而这种特性并不是必须的,因为这并没什么卵用,一些精简的客户端实现可能简单的返回一般的错误情况,例如 false。
RESP Integers
这种类型就是一个代表整数的以CRLF结尾的字符串,并以“:”字节开头。例如 ":0\r\n", 或 ":1000\r\n" 都是整数响应。
很多Redis命令返回RESP Integers, 像 INCR, LLEN 和 LASTSAVE。
返回的整数并没什么特殊的含义,它就是 INCR 增加后的数字,LASTSAVE 的UNIX时间戳等。但返回的整数可以保证是在64位有符号整数的范围内。
整数响应也被大量的用于表示true或false。例如EXISTS和 SISMEMBER 等命令会返回1表示true, 0表示false。
以下命令会返回一个整数: SETNX, DEL, EXISTS, INCR, INCRBY, DECR, DECRBY, DBSIZE, LASTSAVE, RENAMENX, MOVE, LLEN, SADD, SREM, SISMEMBER, SCARD。
RESP Bulk Strings
Bulk Strings 用于表示一个二进制安全的字符串,最大长度为512M。
Bulk Strings 的编码格式如下:
“$” 后跟字符串字节数(prefix length),以CRLF结束实际的字符串CRLF结束
所以字符串"foobar" 被编码成:
"$6\r\nfoobar\r\n"
空字符串:
"$0\r\n\r\n"
RESP Bulk String 也可以用一种代表Null值的特殊格式来表示不存在的值。这种特殊格式的长度值为-1, 并且没数据,所以Null表示为:
"$-1\r\n"
这称为 Null Bulk String。
当服务器返回Null Bulk String时,客户端API不应该返回空串,而是nil 对象。例如Ruby库应该返回 'nil' 而 C 库应该返回 NULL (或在返回的对象设置特殊的标记),等等。
RESP Arrays
客户端用RESP Arrays向Redis服务器发送命令。同样某些Redis命令要返回一个元素集合时也使用RESP Arrays作为返回的类型。一个例子是LRANGE 命令返回一个元素列表。
RESP Arrays使用以下格式发送:
“*” 为第一个字节,后跟数组的元素个数,然后CRLF。然后是数组中的每一个RESP类型表示的元素。
例如一个空数组表示为:
"*0\r\n"
而有两个RESP Bulk Strings "foo" 和 "bar" 的数组编码为:
"*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n"
正如你所见,在数组前面的 *570b78fce6f4d82c6d7725059f1f48f1CRLF 后,数组中的其他的数据类型一个接一个的连接在一起。例如一个有三个整数的数组编码如下:
"*3\r\n:1\r\n:2\r\n:3\r\n"
数组可以包含混合类型,它不要求所有的元素都是相同的类型。例如,一个有4个interges和1个bulk string的数组可以编码为:
*5\r\n :1\r\n :2\r\n :3\r\n :4\r\n $6\r\n foobar\r\n
(为清晰起见响应被分为多行)。
服务器发送的第一行 *5\r\n 表示后跟有5个响应,然后每个代表元素的响应被发送。
Null 数组的概念同样存在,它是Null值的替代方式 (通常使用Null Bulk String,但由于历史原因我们有两种格式)。
例如当BLPOP命令超时,它返回一个长度为-1的Null 数组,如下所示:
"*-1\r\n"
在服务端返回Null数组时,客户端库API应该返回null对象而不是空数组。区分返回空的列表与其他的情况(如BLPOP命令超时的情况)是有必要的。
RESP允许数组的数组。例如一个含两个数组的数组编码如下:
*2\r\n *3\r\n :1\r\n :2\r\n :3\r\n *2\r\n +Foo\r\n -Bar\r\n
高效解析Redis协议
尽管Redis协议非常可读并且容易实现,它却可以兼得二进制协议的高效。
RESP使用长度前缀来传输bulk 数据,所以不需要像JSON一样扫描数据负载中的特殊符号,或者用引号括住数据负载。
Bulk和Multi Bulk长度的处理可以一次处理一个字符,同时可以扫描CR字符,像如下的C代码:
#include <stdio.h> int main(void) { unsigned char *p = "$123\r\n"; int len = 0; p++; while(*p != '\r') { len = (len*10)+(*p - '0'); p++; } /* Now p points at '\r', and the len is in bulk_len. */ printf("%d\n", len); return 0; }
当第一个CR被识别后,后面的LF可以忽略不处理。然后bulk数据可以一次读取而不需要分析 数据负载。最后剩下的CR和LF字符串可以丢弃不处理。
与二进制协议比较性能时,Redis协议在大部分的高级语言实现起来足够简单,减少了客户端软件的bug数量。
注:
1. 协议中的CR和LF相当于分割符,命令间存在多个CRLF不应影响后续解析,应为多个CRLF应被忽略掉。例如:
$> (printf "PING\r\nPING\r\nPING\r\n\r\n\rPING\r\n"; sleep 1) | nc localhost 6379 +PONG +PONG +PONG +PONG
2. 对比一下memcached的协议,redis的协议确实设计得比较精简:
(1) 一致的请求形式。redis的请求都是以 Bluk String 数组发送,不同命令只是数组的元素个数不同,所有命令的处理可以先读取完整个数组再根据不同命令解析数组的参数;而不是像mc协议一样,不同请求的命令格式不同,那么在读取网络字节流的过程中就要对不同命令做不同的处理,增加了协议解析的难度。
(2) 长度前缀是高效解析协议的关键。字段长度信息并不是二进制协议的专利,文本协议也可以有。
更多Redis相关知识,请访问Redis使用教程栏目!
以上是redis协议是什么意思的详细内容。更多信息请关注PHP中文网其他相关文章!

Redis通过缓存数据、实现分布式锁和数据持久化来提升应用性能和可扩展性。1)缓存数据:使用Redis缓存频繁访问的数据,提高数据访问速度。2)分布式锁:利用Redis实现分布式锁,确保在分布式环境中操作的安全性。3)数据持久化:通过RDB和AOF机制保证数据安全性,防止数据丢失。

Redis的数据模型和结构包括五种主要类型:1.字符串(String):用于存储文本或二进制数据,支持原子操作。2.列表(List):有序元素集合,适合队列和堆栈。3.集合(Set):无序唯一元素集合,支持集合运算。4.有序集合(SortedSet):带分数的唯一元素集合,适用于排行榜。5.哈希表(Hash):键值对集合,适合存储对象。

Redis的数据库方法包括内存数据库和键值存储。1)Redis将数据存储在内存中,读写速度快。2)它使用键值对存储数据,支持复杂数据结构,如列表、集合、哈希表和有序集合,适用于缓存和NoSQL数据库。

Redis是一个强大的数据库解决方案,因为它提供了极速性能、丰富的数据结构、高可用性和扩展性、持久化能力以及广泛的生态系统支持。1)极速性能:Redis的数据存储在内存中,读写速度极快,适合高并发和低延迟应用。2)丰富的数据结构:支持多种数据类型,如列表、集合等,适用于多种场景。3)高可用性和扩展性:支持主从复制和集群模式,实现高可用性和水平扩展。4)持久化和数据安全:通过RDB和AOF两种方式实现数据持久化,确保数据的完整性和可靠性。5)广泛的生态系统和社区支持:拥有庞大的生态系统和活跃社区,

Redis的关键特性包括速度、灵活性和丰富的数据结构支持。1)速度:Redis作为内存数据库,读写操作几乎瞬时,适用于缓存和会话管理。2)灵活性:支持多种数据结构,如字符串、列表、集合等,适用于复杂数据处理。3)数据结构支持:提供字符串、列表、集合、哈希表等,适合不同业务需求。

Redis的核心功能是高性能的内存数据存储和处理系统。1)高速数据访问:Redis将数据存储在内存中,提供微秒级别的读写速度。2)丰富的数据结构:支持字符串、列表、集合等,适应多种应用场景。3)持久化:通过RDB和AOF方式将数据持久化到磁盘。4)发布订阅:可用于消息队列或实时通信系统。

Redis支持多种数据结构,具体包括:1.字符串(String),适合存储单一值数据;2.列表(List),适用于队列和栈;3.集合(Set),用于存储不重复数据;4.有序集合(SortedSet),适用于排行榜和优先级队列;5.哈希表(Hash),适合存储对象或结构化数据。

Redis计数器是一种使用Redis键值对存储来实现计数操作的机制,包含以下步骤:创建计数器键、增加计数、减少计数、重置计数和获取计数。Redis计数器的优势包括速度快、高并发、持久性和简单易用。它可用于用户访问计数、实时指标跟踪、游戏分数和排名以及订单处理计数等场景。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

Atom编辑器mac版下载
最流行的的开源编辑器

PhpStorm Mac 版本
最新(2018.2.1 )专业的PHP集成开发工具

禅工作室 13.0.1
功能强大的PHP集成开发环境

WebStorm Mac版
好用的JavaScript开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)