Use Go to learn about Redis communication protocol
Original address: Fried fish of the fan portal
Go, PHP, Java ... have so many packages to support your use of Redis, have you ever thought about
With the service side, with the client, they are how to communicate, and based on what communication protocol to make the interaction?
Introduced
Based on our purpose, this paper mainly explains and practices the communication protocol of Redis.
The client and server side of Redis is data interaction over a TCP connection, with the default port number of 6379
The commands or data sent by the client and the server are \r\n
all terminated (CRLF) (this is a convention)
Agreement
There are requests and replies in Redis, and the request agreement is divided into new and legacy versions, the new unified request Protocol was introduced in Redis 1.2, and eventually became the standard way for Redis server communication in Redis version 2.0.
This article is based on the new version of the Protocol to achieve functionality, not recommended to use the old version (1.2 is old). Here are a few examples of new protocols:
Request Agreement
1. Format example
*<参数数量> CR LF$<参数 1 的字节数量> CR LF<参数 1 的数据> CR LF...$<参数 N 的字节数量> CR LF<参数 N 的数据> CR LF
All parameters sent to the Redis server under this Protocol are binary security (binary safe)
2. Printing examples
*3$3SET$5mykey$7myvalue
3. Actual protocol value
"*3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$7\r\nmyvalue\r\n"
This is the REDIS request protocol specification, according to sample 1 to write the client logic, the final send is example 3, I believe you already have a general concept, Redis protocol is very simple and understandable, this is also a good reason to get started, you can think of the benefits of the definition of the agreement?
Reply
Redis will return many different types of replies depending on the protocol you are requesting (the result of the command being executed is also different). In this reply "protocol", you can check the first byte to determine what type of reply this is, as follows:
- The first byte of State reply (status reply) is "+"
- The first byte of the error reply (Reply) is "-"
- The first byte of an integer reply (integer reply) is ":"
- The first byte of a bulk reply (bulk Reply) is "$"
- The first byte of a multiple bulk reply (multi bulk Reply) is "*"
With the head logo of the reply, the end of the CRLF, you can roughly guess the reply to the "agreement" is how, but the practice to come to the truth, Mr. Saito know that you will soon forget
Practice
Interacting with Redis servers
Package Mainimport ("Log" "NET" "OS" "Github.com/eddycjy/redis-protocol-example/protocol") const (Address = "127.0.0.1:6379" network = "tcp") Func Conn (network, address string) (net. Conn, error) {Conn, err: = Net. Dial (Network, address) if err! = Nil {return nil, err} return conn, Nil}func Main () {//Read into parameter args: = os. Args[1:] If Len (args) <= 0 {log. Fatalf ("Os.args <= 0")}//Get request Agreement reqcommand: = protocol. Getrequest (args)//Connect Redis server Redisconn, err: = Conn (Network, Address) if err! = Nil {log. Fatalf ("Conn err:%v", err)} defer redisconn.close ()//write Request content _, Err = Redisconn.write (Reqcommand) If err! = Nil {log. Fatalf ("Conn Write err:%v", err)}//Read reply command: = make ([]byte, 1024x768) n, err: = Redisconn.read (com Mand) If err! = Nil {log. Fatalf ("Conn Read err:%v", err)}//Processing reply reply, err: = protocol. GeTreply (Command[:n]) if err! = Nil {log. Fatalf ("protocol. Getreply err:%v ", err)}//After processing the contents of the reply log. Printf ("Reply:%v", Reply)//original reply content log. Printf ("Command:%v", String (Command[:n]))}
Here we complete the process of interaction between the Redis client and the server, respectively, as follows:
1. Read command line parameters: Get the Redis command executed
2. Get Request Protocol Parameters
3. Connect to Redis server, get connection handle
4. Write the request protocol parameters to the connection: command-line arguments to send the request
5. Read the returned data from the connection: read the previously requested reply data
6, according to reply "agreement" content, processing the data set of reply
7, the reply content after the output processing and the original reply content
Request
func GetRequest(args []string) []byte { req := []string{ "*" + strconv.Itoa(len(args)), } for _, arg := range args { req = append(req, "$"+strconv.Itoa(len(arg))) req = append(req, arg) } str := strings.Join(req, "\r\n") return []byte(str + "\r\n")}
Through the analysis of Redis request protocol, it can get its law, plus the flag bit, calculate the total number of parameters, then loop the number of bytes of each parameter, the value can be
Reply
Func getreply (Reply []byte) (interface{}, error) {replytype: = reply[0] Switch Replytype {case statusreply: Return dostatusreply (reply[1:]) case Errorreply:return doerrorreply (reply[1:]) Case integerreply: Return dointegerreply (reply[1:]) case Bulkreply:return dobulkreply (reply[1:]) Case Multibulkreply:r Eturn domultibulkreply (reply[1:]) Default:return nil, nil}}func dostatusreply (reply []byte) (String, error) {if len (reply) = = 3 && reply[1] = = ' O ' && reply[2] = = ' K ' {return okreply, nil} If Len (reply) = = 5 && reply[1] = = ' P ' && reply[2] = = ' O ' && reply[3] = = ' N ' && reply[4] = = ' G ' { Return pongreply, nil} return string (Reply), Nil}func doerrorreply (reply []byte) (string, error) {Retur n String (Reply), Nil}func dointegerreply (reply []byte) (int, error) {pos: = Getflagpos (' \ R ', reply) result, err: = StrConv. Atoi (String (reply[:p OS]) if err! = Nil {return 0, err} return result, nil} ...
Here we have all the response types are distributed, different response flags corresponding to different processing methods, there are several issues to note here, as follows:
1. When the requested value does not exist, a special value of 1 is used as a reply
2. All strings sent by the server are terminated by CRLF
3, many batch reply is can be based on batch reply, should pay attention to understand
4, no content of multiple batch reply is present
Most importantly, the control of the rules for different responses will give you a better understanding of how Redis's requests and responses interact.
Summary
The reason for writing this article is because often when using Redis, you don't know what kind of communication protocol it is based on, so it feels very uncomfortable.
Through this article, I believe you have a general understanding of how the Redis client interacts with the server, but also clear the principles of its use of communication, I hope to be able to help you!
Finally, if you want to see the code in detail, turn right at the project address: Https://github.com/EDDYCJY/re ...
If it helps, you're welcome to a Star.
Reference