Go-redis Source Analysis (i): Redis protocol

Source: Internet
Author: User
Tags redis server
This is a creation in Article, where the information may have evolved or changed.

The REDIS.V5 is a Golang-based Redis operations library that encapsulates the various operations on Redis

Source Address is
Https://github.com/go-redis/redis

The Redis client's work essentially transmits the REDIS protocol-compliant command request to Redis server based on the TCP protocol and resolves the server-side return value based on the Redis protocol
We can use the Telnet tool to simulate this process, such as a ping command that we can send requests to

$ telnet 127.0.0.1 6379Trying 127.0.0.1...Connected to 127.0.0.1.Escape character is '^]'.// 以下是发送的内容*1$4PING// 这是redis server返回内容+PONG

So to understand the Redis client, you should first familiarize yourself with the Redis protocol
The Redis protocol consists of two parts, the request protocol and the response protocol , which are very simple communication protocols, easy to program parsing and easy for human to read.
It is important to note that earlier versions of the Redis protocol are not the same as they are today, so the special reminder is that this article is based on the Redis 3.2.6 version.

Request Agreement:

* <参数数量> CR LF$ <参数 1 的字节数量> CR LF<参数 1 的数据> CR LF... $ <参数 N 的字节数量> CR LF<参数 N 的数据> CR LF

We use the initial Telnet simulation to send the ping command as an example
The number of commands for this transmission is followed by the first planetary number. 1 indicates that the request has only one parameter, the same argument is two (get key) for the get command, so it should be written as 2 for the Get parameter
followed by a pass request parameter, each parameter is represented by two lines, where the previous line $n represents the number of characters in the argument, and the next line is the string of the argument
For example, $4 indicates that the command has 4 characters, and the next line of Ping is the string representation of the command.

In the same way, the set command can be written like this

*3$3SET$3key$5value

This can be written in a byte array

"*3\r\n$3\r\nset\r\n$3key\r\n$5value\r\n"

The return value is

+OK

The description command was successfully parsed and executed

Response protocol:

Having said the request protocol, let's look at the response protocol, which is a little more complicated than the request protocol with a uniform format, because the responses to different commands are different, so let's look at each

First, the first byte of the Redis return text indicates the type of response, where the response type is as follows:

状态响应(status reply)的第一个字节是 "+"错误响应(error reply)的第一个字节是 "-"整数响应(integer reply)的第一个字节是 ":"主体响应(bulk reply)的第一个字节是 "$"批量主体响应(multi bulk reply)的第一个字节是 "*"

For example, for a ping command, if it is able to ping, it returns "+pong", which is a status response

    • Status response
      For a status response, the general processing is the character after the client returns "+", for example, the ping command returns "PONG", and the SET command returns "OK"

    • Error response
      The handling of the error response is similar to the status response because, in a sense, the error is a state, but a special state, so the handling of the error response is to return the character after "-"

    • Integer response
      The integer response is to handle commands such as Incr,ttl, which return an integer directly, and the general process is to return an integer number after ":".

    • Principal response
      The principal response is used to return a string, which is the most common form of response, such as all commands that get a string, such as a GET command, that are obtained by the principal response or by the bulk principal ring protocol.
      The number after the first line of the principal response, "$", indicates the length of the returned string, and the next line returns the string literal. If the string is empty, then the first row returns "$-1"

    • Bulk Body Response
      The bulk body response is the server-side batch return string protocol, very similar to the request protocol, the number after the first line "*" indicates how many of the strings returned this time, and then returns the string in the principal response protocol

Well, here we have a general understanding of Redis's communication protocol. Although we are in the analysis of other people write code, but the end of the paper on the light, it is known that the matter to preach, in the analysis of the source code is very useful when you personally knock some codes. So I used Golang to write a small program to simulate the Redis communication protocol, due to the relative responsibility of the response protocol, we temporarily to simulate the state response and the main response of two protocols

The Golang code is as follows:

Package Mainimport ("FMT" "OS" "Net" "StrConv") const (redisserveraddress = "127.0.0.1:6379" Redisserve Rnetwork = "tcp") type Rediserror struct {msg string}func (this *rediserror) Error () string {return this.msg}//connected to Redis Serverfunc Conn () (NET. Conn, error) {Conn, err: = Net. Dial (Redisservernetwork, redisserveraddress) if err! = Nil {fmt. Println (Err. Error ()) OS. Exit (1)} return conn, err}//converts the parameter to the REDIS request protocol func getcmd (args []string) []byte {cmdstring: = "*" + StrConv. Itoa (len (args)) + "\ r \ n" for _, V: = Range args {cmdstring + = "$" + StrConv. Itoa (Len (v)) + "\ r \ n" + V + "\ r \ n"} cmdbyte: = make ([]byte, Len (cmdstring)) copy (cmdbyte[:], cmdstring) retur  n Cmdbyte}func dealreply (reply []byte) (interface{}, error) {responsetype: = reply[0] Switch Responsetype {case ' + ': return dealstatusreply (Reply) Case ' $ ': return dealbulkreply (Reply) Default:return nil, &rediserror{"Proto wrong!"}  }}//Processing Status response func dealstatusreply (reply []byte) (interface{}, error) {statusbyte: = reply[1:] pos: = 0 for _, V: = Range Statusbyte {if v = = ' \ r ' {break} pos++} Status: = statusbyte[:p OS] ret Urn string (status), nil}//handles the body response func dealbulkreply (reply []byte) (interface{}, error) {statusbyte: = reply[1:]// Gets the response string length indicated in the first line of the response text pos: = 0 for _, V: = range Statusbyte {if v = = ' \ r ' {break} P os++} strlen, err: = StrConv. Atoi (String (statusbyte[:p OS])) if err! = Nil {fmt. Println (Err. Error ()) OS.  Exit (1)} if strlen = =-1 {return ' nil ', nil} nextlinepost: = 1 for _, V: = range Statusbyte {if V = = ' \ n ' {break} nextlinepost++} Result: = String (statusbyte[nextlinepost:nextlinepost+s Trlen]) return result, Nil}func main () {args: = os. Args[1:] If len (args) = = 0 {fmt. Println ("Usage:go RUn proto.go + redis command\nfor Example:\ngo run proto.go PING ") os. Exit (0)} conn, _: = conn () cmd: = Getcmd (args) conn. Write (cmd) BUF: = Make ([]byte, 1024x768) n, _: = conn. Read (BUF) Res, _: = Dealreply (Buf[:n]) fmt. Println ("Redis's return result is", RES)}

To run the code:

// 测试PING命令$go run proto.go PINGredis的返回结果是  PONG// 测试SET命令$go run proto.go SET key valueredis的返回结果是  OK// 测试GET命令(GET一个存在的键)$go run proto.go GET key redis的返回结果是  value// 测试GET命令(GET一个不存在的键)$go run proto.go GET not_exist_key redis的返回结果是  nil

All ok!

PS: This test code is very sloppy, many exceptions are not considered, mainly to test the understanding of Redis

Article reference
Http://doc.redisfans.com/topic/protocol.html

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.