Abstract: I am a Redis service, the most proud of is my speed, my QPS can reach 100,000 level.

This article is from Redis: How I Communicate with a Client.

River’s lake said, the world martial arts, invincible, only fast not broken, this sentence is tailor-made for me.

I am a Redis service, the most proud of is my speed, my QPS can reach 100,000 level.

There are countless younger brothers in my staff, they will come to me from time to time to store or take away some data. I call them clients and give them the English name redis-client.

Sometimes one little brother would come very frequently, sometimes a lot of little brothers would come at the same time, but I could manage even more little brothers in order.

“My younger brothers asked me one day.

In order not to let my younger brothers slow me down, I racked my brains and developed the following three principles when designing the communication protocol with them:

  • Implement a simple

  • Fast parsing for computers

  • For humans, it’s readable

Why is that? Let’s take a look at the process of issuing an instruction. First, the instruction operation needs to be encapsulated in the client side and transmitted through the network. Finally, the corresponding parsing and execution are carried out in the server side.

If this process is designed as a very complex protocol, the process of encapsulation, parsing and transmission will be very time-consuming, which will undoubtedly slow down my speed. What, you ask me why I follow that last rule? As a gift to the programmers, I am so kind.

The Protocol I created is called RESP (REdis Serialization Protocol). It works on the upper layer of TCP and serves as a standard form of communication between me and the client.

Speaking of which, I can’t wait to show you what I’ve designed, but I’m a big brother, and I need to be a little cocky, so I can’t offer it to you.

Therefore, I suggest that you directly use the client to send a command to the server, and then retrieve the corresponding message of this command to have a visual look. Having said that, BUT I have been encapsulated very tightly, under normal circumstances you can not see my internal communication of the specific message, so, you can disguise as a Redis server, to intercept the message sent to me by my younger brothers.

It is also very simple to implement. The communication between my younger brother and I is based on Socket, so I start a ServerSocket locally to listen to port 6379 of Redis service:

public static void server() throws IOException {
    ServerSocket serverSocket = new ServerSocket(6379);
    Socket socket = serverSocket.accept();
    byte[] bytes = new byte[1024];
    InputStream input = socket.getInputStream();
    while(input.read(bytes)!=0){
        System.out.println(new String(bytes));
    }
}
Copy the code

Then start the Redis-CLI client and send a command:

set key1 value1
Copy the code

The masquerade server receives the message and prints it on the console:

*3
$3
set
$4
key1
$6
value1
Copy the code

Here, I can see some of the keywords I just typed, but there are some other characters, how to explain, it is time for me to reveal the format of the protocol message.

I told the boys, when you talk to the big brother, you have to play by the rules, so here are the rules to follow when you ask:

*< parameter number > CRLF $< parameter 1 byte length > CRLF < parameter 1 data > CRLF $< parameter 2 byte length > CRLF < parameter 2 data > CRLF... $< bytes of parameter N > CRLF < data of parameter N > CRLFCopy the code

First, the CRLF at the end of each line, translated into programming language, is \r\n, which means carriage return plus line feed. You can see why the commands printed on the console are vertical.

During command parsing, set, key1, and value1 are considered as three parameters. Therefore, the number of parameters is 3, corresponding to *3 in the first line.

The first parameter, set, has length 3 corresponding to 3; The second argument, key1, has length 4 corresponding to 4; The third argument, value1, is of length 6 and corresponds to $6. The next line of each parameter length corresponds to the actual parameter data.

Is it easy to understand how an instruction is converted into a protocol message?

When the younger brother sent to me after the request, as the eldest brother, I will be on the younger brother’s request for instructions to reply, and I have to classify according to the reply content, otherwise the younger brother should be confused with my instructions.

Simple string

A simple string reply is a one-line reply that begins with +, does not allow line breaks, and ends with \r\n. There are many instructions that will only reply with an OK after successful execution. This format is used to effectively reduce transmission and parsing overhead.

Error response

In THE RESP protocol, the error reply can be used as a variant of a simple string reply. The format is very similar except that the first character starts with -. The content of the error reply is usually the error type and the string describing the error.

Error reply occurs in some abnormal scenarios, such as when the wrong command is sent or the number of operands is not correct. When the client receives an error reply, it is distinguished from a simple string reply as an exception.

Integer reply

The integer reply is also widely used, starting with: and ending with \r\n, to return an integer. For example, integer responses are used when incr returns an incremented value, llen returns the length of an array, or the 0 or 1 returned by the EXISTS command as a basis for determining the existence of a key.

Batch reply

Batch replies are multi-line string replies. It starts with $, followed by the length of bytes sent, then \r\n, then sends the actual data, and finally ends with \r\n. If the data to be replied does not exist, the reply length is -1.

Multiple batch reply

Multiple batch replies are used when the server is returning multiple values, such as a collection of elements. It starts with *, followed by the number of elements returned, followed by multiple batch replies described above.

Here, basically I and little brother between the communication protocol on the end of the introduction. Just now you’ve tried masquerading as a server, but now you’ll try writing a client that will interact with me directly.

private static void client() throws IOException { String CRLF="\r\n"; Socket socket=new Socket("localhost", 6379); try (OutputStream out = socket.getOutputStream()) { StringBuffer sb=new StringBuffer(); sb.append("*3").append(CRLF) .append("$3").append(CRLF).append("set").append(CRLF) .append("$4").append(CRLF).append("key1").append(CRLF) .append("$6").append(CRLF).append("value1").append(CRLF); out.write(sb.toString().getBytes()); out.flush(); try (InputStream inputStream = socket.getInputStream()) { byte[] buff = new byte[1024]; int len = inputStream.read(buff); if (len > 0) { String ret = new String(buff, 0, len); System.out.println("Recv:" + ret); }}}}Copy the code

Run the above code and the console outputs:

Recv:+OK
Copy the code

This mimics the client issuing the set command and receiving a reply. And so on, you can encapsulate other commands yourself and implement your own Redis client to communicate with me.

But remember, call me big brother.

Click to follow, the first time to learn about Huawei cloud fresh technology ~