How do Redis server and client communicate?

(1) With the problem we will learn how to achieve the bottom of Redis, we know that Redis persistence has two ways:

1. The first method is RDB to achieve persistence:

RDB persistence refers to writing snapshots of data sets in memory to disks at a specified interval. The actual operation is to fork a sub-process to write data sets to temporary files first. After the data is written successfully, the original files are replaced and stored in binary compression. So it is a full way to persist, here also collated a Redis 300-page study notes, to share with you!

Advantages:

  • Once you do this, your entire Redis database will contain only one file, making it easy to back up. For example, you might plan to file some data every day.
  • For easy backup, we can easily move RDB files one by one to another storage medium
  • RDB can recover large data sets faster than AOF.
  • RDB maximizes the performance of Redis: the only thing the parent has to do to save the RDB file is fork out a child, which then handles all subsequent saves without the parent performing any disk I/O operations.

Disadvantages:

  • If you need to avoid losing data in the event of a server failure, the RDB is not for you. Although Redis allows you to set different save points to control how often RDB files are saved, it is not an easy operation because RDB files need to hold the state of the entire data set. So you’ll probably save your RDB file at least once every 5 minutes. In this case, you could lose several minutes of data in the event of a malfunctioning outage.
  • Each time the RDB is saved, Redis forks () out a child process that does the actual persistence. In large data sets, fork() can be time-consuming, causing the server to stop processing the client in so-and-so milliseconds; If the data set is very large and CPU time is very tight, this stop time can even take a full second. Although AOF overrides also require forking (), the durability of the data is not compromised regardless of the interval between AOF overrides.

2. The second approach is AOF

AOF persistence records every write and delete operation processed by the server in the form of logs. The query operation is not recorded in the form of text. You can open the file to see detailed operation records. So he persisted incrementally (that is, he persisted little by little, not all at once), but ultimately logged instructions like this

//k123456 //$21/21 / value //hello I am is wangwei 1234567 //hello I am is wangwei 1234567Copy the code

Advantages:

  • Using AOF persistence makes Redis much more durable: You can set different fsync policies, such as no fsync, fsync every second, or fsync every time a write command is executed. The default AOF policy is fsync once per second. In this configuration, Redis still performs well and loses at most a second of data in the event of an outage (fsync is performed in background threads, so the main thread can continue to struggle to process command requests).

  • The AOF file is an append only log file, so writes to the AOF file do not need to seek, even if the log contains incomplete commands for some reason (for example, the disk is full when writing, the write is stopped, etc.). The Redis-check-aof tool can also easily fix this problem. Redis can automatically rewrite the AOF in the background when the AOF file becomes too large: the rewritten new AOF file contains the minimum set of commands needed to restore the current data set. The entire rewrite operation is absolutely safe because Redis continues to append commands to existing AOF files while creating new AOF files, and the existing AOF files will not be lost even if an outage occurs during the rewrite. Once the new AOF file is created, Redis switches from the old AOF file to the new AOF file and starts appending the new AOF file.

  • AOF files orderly store all writes to the database in the Redis protocol format, so the contents of AOF files are easy to read and parse. Exporting AOF files is also very simple: For example, if you accidentally execute the FLUSHALL command, as long as the AOF file isn’t overwritten, stop the server, remove the FLUSHALL command at the end of the AOF file, and restart Redis, You can restore the data set to the state it was in before the FLUSHALL execution.

Disadvantages:

  • AOF files are usually larger than RDB files for the same data set.

  • Depending on the fsync strategy used, AOF may be slower than RDB. Fsync per second performance is still very high under normal conditions, and turning off fsync allows the AOF to be as fast as the RDB, even under high loads. However, RDB can provide more guaranteed maximum latency when handling large write loads.

  • AOF has had a bug in the past where an AOF file could not restore the dataset as it was saved when it was reloaded due to certain commands. (For example, the blocking command BRPOPLPUSH has caused such a bug.) The test suite adds tests for this: they automatically generate random, complex data sets and reload them to make sure everything is okay. Although this kind of bug is not common in AOF files, RDB bugs are almost impossible by comparison.

(2) We write a Redis client (take String set and GET methods as examples)

You can also see a lot of Redis clients in the market, such as Jedis, Redission, RedisTemplate… Are different Redis clients, in fact, the underlying implementation is based on the case we are going to do to achieve.

1. A client like Jedis can be implemented through a handwritten implementation of the client code

public class RedisClient { OutputStream outputStream; InputStream inputStream; Public RedisClient(String host,int port) throws IOException {// Establish a connection between Java and the client. Socket Socket = new Socket(host,port); OutputStream = socket.getOutputStream(); InputStream = socket.getinputStream (); } public void set(String key ,String value) throws IOException { //1. StringBuffer data = new StringBuffer(); data.append("*3").append("\r\n"); data.append("$3").append("\r\n"); data.append("SET").append("\r\n"); System.out.println(data.toString()); data.append("$").append(key.getBytes().length).append("\r\n"); data.append(key).append("\r\n"); System.out.println(data.toString()); data.append("$").append(value.getBytes().length).append("\r\n"); data.append(value).append("\r\n"); System.out.println(data.toString()); //*3 //$3 //SET //$7 //k123456 //$21 // 21 // /hello I am wangwei //2 Write (data.toString().getBytes())); System.out.println(" send successfully ----->"); System.out.println(data); Byte [] Response = new byte[1024]; inputStream.read(response); System.out.println(" received response ---->"); System.out.println(response.toString()); Public void get(String key) throws IOException {//1. StringBuffer data = new StringBuffer(); data.append("*3").append("\r\n"); data.append("$3").append("\r\n"); data.append("GET").append("\r\n"); System.out.println(data.toString()); data.append("$").append(key.getBytes().length).append("\r\n"); data.append(key).append("\r\n"); System.out.println(data.toString()); //2. Then send the command to Redis server outputStream.write(data.toString().getbytes ()); System.out.println("get method sent successfully ----->"); System.out.println(data); Byte [] Response = new byte[1024]; inputStream.read(response); System.out.println("get method receives response ---->"); System.out.println(response.toString()); } public static void main(String[] args) throws IOException { RedisClient redisClient = new RedisClient (" 127.0.0.1 ", 6379); redisClient.set("k123456","hello I am is wangwei"); redisClient.get("k123456"); }} 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646 5666768697071727374757677787980818283848586878889Copy the code

2. Test case – First to clear the redis client key, now there is no data in Redis

3. After I run the RedisClient class written above, I call it in the main method

public static void main(String[] args) throws IOException {

RedisClient = new RedisClient("127.0.0.1",6379); redisClient.set("k123456","hello I am is wangwei"); redisClient.get("k123456"); } 1234567Copy the code

4. Now I have not entered any command line in redis-cli. exe client, so if I go to redis-cli. exe get “k123456”, If I get the value “Hello I am is wangwei”, my handwritten set method is working. If I don’t get the value, my handwritten set method is not working. When I first get K123456, I didn’t get the value because I forgot to run main. Here is also a Redis 300-page study notes to share with you!

The last

Welcome everyone to exchange, like the article remember to pay attention to me like yo, thank you for your support!