JIYIK CN >

Current Location:Home > Learning > NETWORK >

Redis protocol detailed explanation

Author:JIYIK Last Updated:2025/03/18 Views:

In the article "Two Ways to Operate Redis with PHP" , we introduced how to use PHP to encapsulate phpredis. However, we don't know much about the underlying redis protocol. This article briefly introduces the Redis protocol to facilitate your use in programming in the future.

The protocol for Redis clients and Redis servers to communicate is called RESP (REdis Serialization Protocol). Although RESP is specifically designed for Redis, it can also be used in other CS software projects.

RESP is a compromise between the following options:

· Easy to implement
· Quick analysis
· High readability

RESP can serialize different data types, such as integers, strings, and arrays. In addition to these, RESP also specifies a data type for error messages. The Redis client sends an array of string parameters of the command to be executed as a request to the Redis server. The Redis server responds with the data type of the specified command.

It should be noted that the Redis protocol summarized here only applies to client and server communication. Redis cluster uses a different binary protocol to transmit information between different nodes.

Network Layer

The port that the Redis service listens on is 6379. A TCP connection will be created between the client and the server, and its connection port is 6379.

RESP Protocol Description

The RESP protocol was introduced into Redis in Redis 1.2, but it became the standard way to communicate with the Redis server in Redis 2.0. The RESP protocol is the protocol that we need to implement in the Redis client.

In fact, RESP is a serialization protocol that supports the following data types: Simple String, Errors, Integers, Bulk Strings and arrays.

RESP implements the request-response protocol as follows:

The client encapsulates the command into a complex string array and sends it to the Redis server.
The server converts the execution result of the received command into RESP type data and returns it to the client.

In RESP, we will determine the type of data based on the first byte of the response information:

+ indicates a Simple Strings
- indicates an Error message
: indicates an integer data
$ indicates Bulk Strings
* indicates an array

In addition, RESP can also represent a NULL value. This will be introduced below. In RESP, different parts of the protocol content are marked with "\r\n" as the end mark.

Simple Strings Response

Simple Strings The reply is encoded as follows: it starts with a plus sign (+), followed by a string that does not contain CR or LF characters, and ends with CRLF (\r\n).

Simple Strings uses the lowest payload to transmit non-binary safe strings. For example, after many Redis commands are successfully executed, only OK is needed to inform the client that the command has been successfully executed. In this way, the response string will encode OK as follows according to the encoding method of Simple Strings of RESP:

"+OK\r\n"

In order to send binary-safe strings, RESP Bulk Strings will replace the Simple Strings encoding method.

When the Redis server responds using Simple Strings, the client needs to return a string to the caller, which consists of the string after the plus sign (+). In this example, it is OK.

RESP Errors

RESP has a special type for error messages. In fact, error types are very similar to Simple Strings. The difference is that the first byte is different. Error types start with a minus sign (-). The essential difference is that error messages are treated as exceptions on the client side. The error message itself identifies the type of error.

The basic format is as follows

“-Error message\r\n”

Error messages are sent to the client only when some error occurs. For example, if you are processing an incorrect data type, or sending a command that does not exist, etc. In these cases, the client will receive an error message.

The following is an example of an error response:

-ERR unknown command 'onmpw'
-WRONGTYPE Operation against a key holding the wrong kind of value

The string from the first character after the minus sign (-) to the first space or newline character indicates the type of error. This is just for convenience when using Redis, it is not part of RESP.

The Redis client returns different exceptions to the caller based on different types of errors, or provides a common method to handle these errors by providing the error message name as a string to the caller.

However, you don't need to spend too much time thinking about the error type, because it is rarely used, and some clients that are not very powerful may just return a false for the error message.

RESP integer response

This type also uses CRLF (\r\n) as the end mark. Its first byte is a colon (:). Its format is as follows

:0\r\n
:1000\r\n

Many Redis commands return integers as their results, like INCR, LLEN, and LASTSAVE.

These integer numbers do not have any special meaning. For the INCR command, it is an increasing number; for LASTSAVE, it is a UNIX timestamp, etc. However, it should be noted that the range of integers is a signed 64-bit integer range.

Sometimes, integer responses are used to represent true and false. For example, the EXISTS or SISMEMBER commands use 1 for true and 0 for false.

RESP Bulk Strings响应

Bulk Strings的使用是为了表示一个二进制安全的字符串。这个字符串的长度可以达到512MB。

Bulk Strings使用如下的形式进行编码

· 用$符号后面跟着一个整数的形式组成一个字符串(长度前缀),以CRLF结尾。
· 实际的字符串。
· 整个字符串后面使用CRLF结束。

字符串“onmpw”的编码形式如下:

“$5\r\nonmpw\r\n”

空字符串的形式如下:

“$0\r\n\r\n”

除此之外,Bulk Strings还可以使用一个特殊的标识来表示一个不存在的值。这个值就是上面我们提到过的NULL值。其表示形式如下:

“$-1\r\n”

这被称为Null Bulk String。

当请求的对象不存在的时候,客户端的API不要返回一个空字符串,应该返回一个nil对象。就好像一个Ruby库应该返回一个nil,C库应该返回一个NULL等等。

RESP 数组

客户端想Redis服务端发送命令的时候,使用的是RESP 数组的形式。并且还有一些特定的命令的返回结果也是一个元素的集合。这些返回的结果也是用RESP数组的形式编码的。 比如说命令LRANGE就返回一些列的元素。

RESP Arrays使用如下的形式发送信息:

· 星号(*)作为第一个字节,后面跟着一个十进制的整数,接着是CRLF(\r\n)。
· 对每一个数组的元素都有一个额外的RESP类型。

空数组的形式如下:

“*0\r\n”

对于有两个Bulk Strings元素foo和bar的Array的表示形式如下:

“*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n”

Arrays除了包含有Bulk Strings元素外还可以包含整型元素

“*3\r\n:1\r\n:2\r\n:3\r\n”

当然,Array中的元素就像PHP数组一样,里面的元素的类型可以是混合的。看下面的例子

“*5\r\n:1\r\n:2\r\n:3\r\n:4\r\n$5\r\nonmpw\r\n”

为了看得清楚,我们将上面的字符串分成多行表示

*5\r\n
:1\r\n
:2\r\n
:3\r\n
:4\r\n
$5\r\n
onmpw\r\n

服务端发送的第一行是*5\r\n,表示后面跟着有5个响应信息。每一条响应信息组成了一个Multi Bulk响应被传输到客户端。

在Bulk Strings类型中我们可以表示NULL值。同样的,在Arrays中也可以表示一个空Array。使用RESP Arrays的类型表示NULL的形式如下:

“*-1\r\n”

注意,当Redis响应一个NULL Array的时候,客户端的API返回的不应该是一个空数组,而应该返回一个null对象。

和编程语言的数组一样,RESP Arrays是可以嵌套的。下面我们看嵌套两层的Array的形式——也就是对应我们编程语言中的二维数组。同样为了表示清楚,我们使用换行的方式表示。

*2\r\n
*3\r\n
:1\r\n
:2\r\n
:3\r\n
*2\r\n
+Foo\r\n
-Bar\r\n

在上面的数据中,*2\r\n表示的是有两个元素,从*3和下面的*2我们可以看出这两个元素都是RESP Arrays类型的。并且*3表示在该子数组中有三个元素,分别是整数1、2还有3;*2表示在该字数组中有两个元素,分别是Simple Strings Foo和错误信息 Bar。

在Arrays中的NULL 元素

一个元素的Array可能会是Null。包含多个元素的Array中也同样会有Null值。例如下面的Arrays数据

*3\r\n
$3\r\n
foo\r\n
$-1\r\n
$3\r\n
bar\r\n

从上面我们可以看到,其中的第二个元素就是Null。客户端类库应该返回的信息如下

[“foo”,nil,”bar”]

向Redis服务端发送命令

如果你已经对RESP序列化格式很熟悉了,接下来写一个Redis客户端应该是很容易的。

· 客户端想Redis服务端发送仅仅包含Bulk Strings元素的Array。
· Redis服务端会向客户端响应任何有效的RESP类型的数据。

举例来说

C: *2\r\n$3\r\nget\r\n$5\r\nmykey\r\n
S: $5\r\nonmpw\r\n

C表示客户端发送给服务端的请求信息。本例中我们发送的命令是 get mykey。S表示是服务端响应的信息,本例中是返回了 onmpw字符串。至于各项的含义上面已经介绍了这里就不重复了。

多命令和管道处理

客户端可以在一个连接上面发送多个命令。流水线的处理方式支持在客户端只由一个写操作来发送多个命令。并且不用等待读取完上一个命令的返回结果就可以进行下一个命令的写操作。所有命令的响应信息都可以在最后进行读取。

关于这一点可以参考page about Pipeling

Inline命令

有些时候仅仅是telnet连接Redis服务,或者是仅仅向Redis服务发送一个命令进行检测。虽然Redis协议可以很容易的实现,但是使用Interactive sessions 并不理想,而且redis-cli也不总是可以使用。基于这些原因,Redis支持特殊的命令来实现上面描述的情况。这些命令的设计是很人性化的,被称作Inline 命令。

下面是一个Inline 命令的例子:

C: PING
S: +PONG

S代表服务端响应,C代表客户端请求。

下面是另一个Inline命令的例子:

C: EXISTS onmpw
S: :1

因为onmpw存在,所以服务端返回:1。这里EXISTS命令只带有一个参数,多个参数可以用空格进行分割。

在对Redis请求协议规范之前,客户端就是用这种用空格分割的命令发送请求。

代码实现

上面大概介绍了Redis的协议。现在我们通过一段PHP代码看一下如何实现Redis客户端。

<?php
class Redis{
   
    private $handle;
   
    private $host;
    private $port;
    private $slient_fail;
    private $timeout;
   
    private $connect_timeout = 3;
   
    public function __construct($host,$port,$slient_fail = false,$timeout = 60){
        if($host && $port){
            $this->connect($host,$port,$slient_fail,$timeout);
        }
    }
   
    private function connect($host = '127.0.0.1',$port = 6379,$slient_fail = false,$timeout = 60){
        $this->host = $host;
        $this->port = $port;
        $this->slient_fail = $slient_fail;
        $this->timeout = $timeout;
        $this->handle = fsockopen($host,$port,$errno,$errstr,$this->connect_timeout);
    }
   
    public function get(){
        $nl = "\r\n";
        $cmd = '*2'.$nl.'$3'.$nl.'get'.$nl.'$5'.$nl.'mykey'.$nl;
        fwrite($this->handle, $cmd);
        $res = fgetc($this->handle);
        $res = trim(fgets($this->handle));
        $response = fread($this->handle,$res);
        fgets($this->handle);
        echo $response;
    }
}
 
$obj = new Redis('192.168.144.133',6379);
$obj->get();

以上就是所有对Redis协议的介绍,希望对大家有所帮助。

For reprinting, please send an email to 1244347461@qq.com for approval. After obtaining the author's consent, kindly include the source as a link.

Article URL:https://www.jiyik.com/en/xwzj/network_9820.html

Related Articles

How to Fix ERR_SSL_PROTOCOL_ERROR Error

Publish Date:2025/03/17 Views:96 Category:NETWORK

If your website won’t load over a secure connection due to an error like ERR_SSL_PROTOCOL_ERROR, then this is the right place to start. In this article, we’ll explain what this type of error means and walk you through how to fix it so y

Expected corresponding JSX closing tag error in React

Publish Date:2025/03/05 Views:121 Category:React

React.js error Expected corresponding JSX closing tag appears when we forget to close a tag in the JSX code. To fix the error, use self-closing tags like input / and make sure the order of opening and closing tags in the JSX code is correct.

Java 错误 java.net.MalformedURLException: No Protocol

Publish Date:2023/07/11 Views:795 Category:Java

我们将研究 Java 中的错误 java.net.MalformedURLException: no protocol。 为什么会发生这种错误,以及我们如何解决该错误。Java 中的 java.net.MalformedURLException: no protocol 错误

使用 Python 获取 Redis 数据库中的所有键

Publish Date:2023/06/18 Views:137 Category:Python

本文将讨论如何使用Python获取 Redis 数据库中的所有键。使用 keys() 获取 Redis 数据库中的所有键 要使用 redis,我们需要安装它; 您可以查看 Redis 下载页面以了解操作方法。

如何在 Django 应用程序中使用 Redis 进行缓存

Publish Date:2023/02/06 Views:250 Category:Python

减轻服务器压力的方法之一是缓存数据。 这是通过在处理数据后缓存数据,然后在下次请求时从缓存中提供数据来完成的。 本篇文章将详细讨论 Redis,解释如何在 Python 应用程序中安装

React 中 Expected corresponding JSX closing tag 错误

Publish Date:2023/01/13 Views:298 Category:React

当我们忘记关闭 JSX 代码中的标签时,会出现 React.js 错误 Expected corresponding JSX closing tag 。 要解决错误,请使用自闭标签,例如 input / 并确保 JSX 代码中开始和结束标签的顺序是正确的。

Scan to Read All Tech Tutorials

Social Media
  • https://www.github.com/onmpw
  • qq:1244347461

Recommended

Tags

Scan the Code
Easier Access Tutorial