`
redis
  • 浏览: 27056 次
  • 性别: Icon_minigender_2
  • 来自: 上海
社区版块
存档分类
最新评论

Redis协议

 
阅读更多

Redis 协议是从以下几个方面做的一个折中方案:

  • 容易实现
  • 机器解析要快
  • 容易被人理解

网络层

客户端通过创建到 6379 端口的 TCP 连接来连接到一个 Redis 服务器。每个 Redis 命令或者客户端和服务器之间传输的数据都以\r\n (CRLF)结束。

请求

Redis可以接受由不同参数组成的命令。只要接收到一个命令,这个命令就会被执行,然后一个答复会被返回给客户端。

新的统一请求协议

新的统一协议是在Redis1.2中引入的,但是在Redis2.0中成为了与Redis服务器交互的标准方式。在统一协议中所有发送到Redis服务器的参数都是二进制安全的。这是总体格式:

*<number of arguments> CR LF
$<number of bytes of argument 1> CR LF
<argument data> CR LF
...
$<number of bytes of argument N> CR LF
<argument data> CR LF

看下这个例子:

*3
$3
SET
$5
mykey
$7
myvalue

这是以上命令以带引号的字符串展现的样子,这样就可以看到这个请求中每个字节的准确内容:

"*3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$7\r\nmyvalue\r\n"

就像你一会将会看到的,这个格式还会被用在Redis回复中。这个被用于每个参数中的格式$6\r\nmydata\r\n叫做Bulk 回复。Redis实际上使用的统一请求协议会返回内容列表,叫做Multi-bulk回复。它是由N个不同的Bulk 回复合在一起,并且有一个字符串前缀*<argc>\r\n其中<argc>是后面参数(Bulk回复)的数量。

回复

Redis会以不同类型的回复对命令进行响应。可以通过服务器发送的第一个字节来判定回复的类型:

  • 如果是单行回复,那么第一个字节是「+」
  • 如果回复的内容是错误信息,那么第一个字节是「_」
  • 如果回复的内容是一个整型数字,那么第一个字节是「:」
  • 如果是bulk回复,那么第一个字节是「$」
  • 如果是multi-bulk回复,那么第一个字节是「*」

状态回复

一个状态回复(或者:单行回复)的格式是以「+」开头,以「\r\n」结束的单行字符串。举个例子:

+OK

客户端库要返回「+」后面的所有内容,这个例子里边是字符串「OK」。

错误回复

错误的发送方式和状态回复很像。唯一的不同是第一个字节用「-」替代了「+」。 错误回复只有当一些奇怪的事情发生时才会被发送,例如如果你想要用错误的数据类型执行一个操作,或者这个命令不存在等等。所以客户端库应该在接收到一个错误回复的时候抛出一个异常。

整形回复

这个类型的回复就是一个代表整数以CRLF结束的字符串,并且用一个字节的字符「:」作为前缀。例如「:0\r\n」,或者「:1000\r\n」都是整形回复。 像INCR或者LASTSAVE命令使用整型回复来返回一个没有特别含义的整型数字。对于INCR来说返回的是增加后的数字,对于LASTSAVE来说是一个UNIX时间等等。 像EXISTS这样的命令会返回1表示true,返回0表示false。 其他命令像SADD,SREM和SETNX在操作实际完成的时候会返回1,否则返回0。 以下命令将会返回整型回复:SETNX, DEL, EXISTS, INCR, INCRBY, DECR, DECRBY, DBSIZE, LASTSAVE, RENAMENX, MOVE, LLEN, SADD, SREM, SISMEMBER, SCARD

Bulk回复

Bulk回复被服务器用来返回一个二进制安全的字符串。

C: GET mykey
S: $6\r\nfoobar\r\n

服务器以这种方式来发送数据:第一行是一个字节的内容「$」,之后跟着具体内容的字节数,接下来是CRLF,然后具体数据内容被发送,接下来是额外的两个字节的CRLF。服务器实际发送的序列是:

"$6\r\nfoobar\r\n"

如果请求的内容不存在,那么bulk回复将会使用特殊值-1作为数据长度,例如:

C: GET nonexistingkey
S: $-1

当请求对象不存在,客户端库API不要返回一个空字符串,应该是一个nil对象。举个例子一个Ruby库应该返回「nil」,一个C库应该返回NULL(或者在回复对象中设置一个特殊标记),等等。

Multi-bulk回复

像LRANGE这类的命令需要返回多个值(列表中的每个元素是一个值,LRANGE需要返回多个元素)。这通过multiple bulk write来实现,其第一行指明后面有多少个bulk write。一个multi bulk回复的第一个字节一直是*。例如:

C: LRANGE mylist 0 3
s: *4
s: $3
s: foo
s: $3
s: bar
s: $5
s: Hello
s: $5
s: World

就像你看到的,multi bulk 回复和使用统一协议发送命令到Redis服务器使用的是同样的格式。 服务器发送的第一行是*4\r\n,用来指出下面将会有四个bulk回复。然后每个bulk write将会被传送。 如果指定的key不存在,那么这个key被认为拥有一个空列表,然后0会做为multi bulk的数量被发送。例如:

C: LRANGE nokey 0 1
S: *0

BLPOP命令超时,它将返回值为nil的multi bulk回复。这个类型的multi bulk的数量为-1并且应该被解释为nil值。例如:

C: BLPOP key 1
S: *-1

当这个发生的时候,一个客户端库API应该返回一个nil对象而不是一个空列表。区分一个空的列表和一个错误条件(比如BLPOP命令的超时条件)是必要的。

Multi-Bulk回复中的Nil元素

一个multi bulk 回复的单个元素可能会存在-1的长度,用来指明这个元素不存在并且不是空字符串。这个可能发生在启用了GET模式选项的SORT命令,并且指定的key不存在。包含一个空元素的multi bulk回复的例子:

S: *3
S: $3
S: foo
S: $-1
S: $3
S: bar

第二个元素是nil。客户端库需要返回如下内容:

["foo",nil,"bar"]

多个命令和管道

一个客户端可以使用相同的连接来发送多个命令。Redis是支持管道的,所以客户端可以通过一次写操作发送多个命令,不需要读取服务器的回复才能发送下一个命令。所有的回复可以在最后读取。 通常情况下Redis服务器和客户端之间会有非常快的连接,所以客户端支持这个特性不是那么重要,但如果一个应用需要在很短的时间里发送大量的命令那么使用管道将会非常快。

发送命令的旧协议

在统一请求协议之前,Redis使用一个不同的协议来发送命令,这个协议仍然被支持因为通过telnet它很容易手写。在这个协议中存在两种命令:

  • inline 命令: 命令很简单,就是用空格把参数分隔开来的字符串。二进制安全是不可能的。
  • Bulk 命令: bulk命令和inline命令几乎是一样的,但是最后一个参数为了能够接受二进制安全的内容,所以需要以特殊的方式进行处理。

Inline命令

向Redis发送命令最简单的方法是使用inline命令。以下是一个服务器/客户端之间使用inline命令进行交互的例子(服务器以S:作为开始,客户端以C:作为开始)

C: PING
S: +PONG

以下是另一个例子,一个返回整数的inline命令:

C: EXISTS somekey
S: :0

由于「somekey」不存在,所以服务器返回「:0」。 注意EXISTS命令只带有一个参数。多个参数以空格进行分隔。

Bulk命令

当一些命令以inline命令发送的时候为了使最后一个参数支持二进制安全,需要以一个特殊的格式发送。这些命令将会把最后一个参数作为「字节计数器」,然后大量的数据会被发送(这些数据可以为二进制安全,因为服务器知道有多少字节需要读取)。 看下面这个例子:

C: SET mykey 6
C: foobar
S: +OK

这个命令的最后一个参数是「6」。这个指明了后面数据,字符串「foobar」的字节数。注意即使这些数据被额外的二个字节大小的CRLF所截断。所有bulk命令的准确格式是:把最后一个参数替换成后面数据的字节数,接下来是数据本身和CRLF。为了能够让程序员更加清晰的理解,这是上面例子中客户端发送的字符串:

"SET mykey 6\r\nfoobar\r\n"

Redis有一个内部的列表,记录了什么命令是inline,什么命令是bulk,所以你需要参考这个来发送命令。强烈推荐使用新的统一请求协议来替代旧的协议。

原文:Protocol specification

2
5
分享到:
评论

相关推荐

    Go-用于服务器端的一个Redis协议Go库

    在Redis这样的内存数据存储系统与Go语言结合时,一个高效的Redis协议库是必不可少的。`go-redisproto`就是这样一个专门针对Go语言设计的Redis协议库,它允许开发者轻松地处理Redis命令的序列化和反序列化,从而实现...

    cpp-KedisServer是一个兼容Redis协议的持久性NoSQL

    cpp-KedisServer项目是一个专为C++开发者设计的、完全兼容Redis协议的持久化NoSQL数据库。它的核心特点在于提供了与Redis相似的API和功能,同时利用了RocksDB作为底层的存储引擎,确保了数据的高效性和持久性。 ...

    基于C#的NewLife.Redis高性能Redis协议封装设计源码

    本项目是基于C#的NewLife.Redis高性能Redis协议封装设计源码,包含119个文件,其中包括95个C#源文件、6个csproj文件、3个YAML文件、2个PNG图片文件、2个pubxml文件、1个Editorconfig文件、1个gitignore文件、1个eddx...

    易语言的Redis协议实现:JimStone 谢栋 Redis协议客户端模块:STRedisClient

    本文将详细介绍如何利用易语言实现对Redis协议的操作,特别是针对JimStone(谢栋)编写的Redis协议客户端模块——STRedisClient。这个模块为易语言开发者提供了一种与Redis服务器通信的便捷方式,使易语言程序能够...

    易语言源码Redis协议客户端易语言模块源码.rar

    本压缩包“易语言源码Redis协议客户端易语言模块源码.rar”包含了使用易语言实现的Redis协议客户端的相关源代码。Redis是一款开源、高性能的键值存储系统,常用于数据库、缓存和消息中间件等场景。通过这个源码,...

    Redis协议客户端模块.rar

    Redis协议客户端模块是连接Redis服务器并执行命令的关键部分,它使得开发者能够通过编程语言与Redis进行交互。本模块主要关注的是如何在易语言环境下实现这一功能。 1. **Redis协议简介** Redis使用简单明了的RESP...

    快速 redis 协议解析器和客户端.zip

    Dart 的 Redis 客户端Dart的Redis协议解析器和客户端设计快速而简单。无需外部包即可运行。支持的功能交易和CAS(检查并设置)模式发布订阅统一码性能和简便性TLS简单的redis是redis 协议的简单序列化器和反序列化器...

    易语言Redis协议客户端易语言模块源码.rar

    易语言Redis协议客户端易语言模块源码.rar 易语言Redis协议客户端易语言模块源码.rar 易语言Redis协议客户端易语言模块源码.rar 易语言Redis协议客户端易语言模块源码.rar 易语言Redis协议客户端易语言模块源码....

    Redis协议客户端易语言模块源码

    资源介绍:。JimStone(谢栋) - Redis协议客户端模块。Redis协议客户端模块:STRedisClient for E。实现了对 Redis 客户端协议的封装。资源作者:。JimStone(谢栋)。资源界面:。资源下载:。

    Tendis是一个完全兼容Redis协议的高性能分布式存储系统 .zip

    Tendis是一个完全兼容Redis协议的高性能分布式存储系统中文文档目录介绍特征立即开始要求建造奔跑和玩耍测试表现硬件规格基准和 QPS 数字不同有效载荷的 QPS贡献支持执照介绍Tendis 是一款完全兼容 Redis 协议的高...

    易语言Redis协议客户端模块

    易语言Redis协议客户端模块源码,Redis协议客户端模块,Initialize,Connect,Timeout,RunCommand,Stop,ConvertStrCommand,ConvertCommandToList,MakeRlt,StrToArray,ArrayToStr,SortStringArray,print,printResult,...

    基于 EventMachine 的 Redis 协议实现.zip

    基于 EventMachine 的 Redis 协议实现EM- REDIS¶ ↑描述¶ ↑由 Salvatore 'antirez' Sanfilippo 开发的基于EventMachine的库,用于与非常酷的Redis数据存储进行交互。模仿了 eventmachine 的 memcached 协议实现,...

    与 Google LevelDB 兼容的 redis 协议前端.zip

    与 Google LevelDB 兼容的 redis 协议前端Redis-Leveldb介绍!!! 注意!!!该项目正在寻找新的维护者,如果您有兴趣,请修复一些已知问题然后联系我,我会将项目转交给您。谢谢。Redis-LevelDB 是与 google 的 leveldb ...

    Redis协议详细规范.pdf

    Redis协议是Redis客户端与服务器之间进行通信的规范,它的全称是RESP(REdis Serialization Protocol),是一种简单、快速且具有可读性的序列化协议。 RESP协议最初在Redis 1.2版本中被引入,在Redis 2.0版本后成为...

    Wireshark 的 Redis 协议解析器.zip

    Wireshark 的 Redis 协议解析器目录redis-wireshark动机用法笔记redis-wireshark动机使用流行工具 Wireshark(以前称为 Ethereal)观察与 Redis 相关的网络活动。用法要使用此功能,请将 redis-wireshark.lua 复制到...

    Redis协议封装,支持.Net Core,Redis协议基础实现Redis/RedisClient位于X组件

    NewLife.Redis 是一个Redis客户端组件,以高性能处理大数据实时...高性能Redis协议封装,支持.Net Core,Redis协议基础实现Redis/RedisClient位于X组件,本库为扩展实现,主要增加列表结构、哈希结构、队列等高级功能。

    dotnet-高性能Redis协议封装支持NetCore经过一年多日均80亿调用量验证

    "dotnet-高性能Redis协议封装支持NetCore经过一年多日均80亿调用量验证"这个项目,显然是一款针对.NET Core平台优化的Redis客户端库,经过大规模实际应用的考验,证明了其稳定性和高效性。 首先,我们要理解Redis的...

    完全兼容redis协议的分布式数据库.zip

    完全兼容redis协议的分布式数据库#Reborn——Redis 的另一个快速分布式解决方案Reborn 是一个用 Go/C 编写的基于代理的高性能 Redis 集群解决方案,是 Redis 的替代品。Reborn 支持多个无状态代理和多个 redis 实例...

    用于构建与 redis 协议兼容的 TCP 服务器,服务的高性能框架.zip

    雷迪奥 用于构建与 redis 协议兼容的服务器/服务的高性能瑞士军刀。部分该存储库分为多个组件root包包含用于构建与 redis 协议兼容的高性能服务器的框架。resp实现了处理 RESP(REdis 序列化协议)的低级原语,包括...

Global site tag (gtag.js) - Google Analytics