“This is the sixth day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

For the systems I have worked with so far, most of the performance bottlenecks are in IO.

For example, a system that used to perform normal pressure measurements on the Intranet, After loading the pre-release environment, the pressure test was carried out on the overall performance of the system, which was particularly strained. After investigation, it was found that the time was mainly concentrated on MySQL and Redis query/update. After investigation of database logs, it was found that the time was basically in IO.

After troubleshooting, we immediately took the following optimization measures for the system:

  • Where you need to use database data, try to query it all at once
  • useCASE WHENMechanism Updates multiple pieces of data at a time

After optimization, the performance is improved, but the performance is still poor. Finally, some interfaces (leaderboards) have the following behaviors:

  • Because the cache data is scattered in multiplezsetIn, how many pieces of user data will be calledzscoreAs well aszrevrankTo get user points or rankings

As a result, the main time of the interface is concentrated on IO. Although the average time of executing an instruction is about 1ms(from sending a request to receiving and returning data), it does not add up.

Therefore, we introduced Redis pipeline mechanism to optimize the cache reading part of the system.

Redis Pipeline

We know that typical Redis is a typical C/S architecture and a request/response model, i.e. :

  • On the same TCP connection, the client sends requests A, B, and C in sequence, and the server sends responses A, B, and C in sequence. Most clients implement this by sending requests A and waiting for the response to return before sending the next request.

In contrast, HTTP2 supports multiple requests over the same TCP connection and the response can arrive unordered

Note that Redis Pipeline is not a command like set,get, etc. Instead, the client packages the command together and sends it to the Redis server for processing. To put it bluntly, if the Redis server detects that the client sends multiple commands at the same time, it will enable the Pipline mechanism, save the response of the command to the response queue, and package it back to the client after processing.

The following Demo uses Go to write a simple Pipline program and record captured packet data:

package main

import (
	"context"
	"fmt"
	"github.com/go-redis/redis/v8"
)

func main(a) {
	rdb := redis.NewClient(&redis.Options{
		Addr:     "192.168.0.15:6379",
		Password: "".// no password set
		DB:       0.// use default DB
	})
	ctx := context.Background()
	pipe := rdb.Pipeline()
	for i := 0; i < 64; i++ {
		pipe.ZRank(ctx, "rank", fmt.Sprintf("u%d", i))
	}
	cmds, err := pipe.Exec(ctx)
	iferr ! =nil&& err ! = redis.Nil {panic(err)
	}
	for _, cmd := range cmds {
		resp := cmd.(*redis.IntCmd)
		rank, err := resp.Result()
		iferr ! =nil&& err ! = redis.Nil {panic(err)
		}
		fmt.Printf("%d\n", rank)
	}
}

Copy the code

As shown in the red box in the following figure, the client does not send the packetpiplineInstead, the command is directly packaged together and sent to the server. Due to the large amount of data, the command is split into two packages.

The response packet of the Redis server is shown as follows

So what if we don’t use Pipeline? The WireShark screenshot is shown below (you can modify and verify the above code by yourself).

The above behavior may not be felt when you are developing on the Intranet, because the RTT between the business server and Redis server is very small, and may even be on the same machine. In a production environment, however, the business server and Redis services are typically deployed separately, and the time spent on these network requests can be significant.

conclusion

  • Redis PipelineRedis provides a batch processing mechanism, not a command
  • useRedis PipelineThe mechanism can effectively reduce the number of network requests and reduce the consumption of multiple IO to provide performance
  • The performance gains from merging IO operations (reducing the number of I/OS) are significant