When I was not in touch with Redis before, I heard my friends in the big data team talking about Redis and thought it was so high-end. It would be nice if our team could use Redis someday. After a long time, we finally introduced Redis technology into our project. Get set means “get set”. When I learned that Redis also has auto-increment and auto-decrement operations, and these operations are atomic, and seckill can use this technology, I felt I was familiar with Redis. A Redis is a get set increment increment. In fact, Redis is far from being as simple as we imagined. Today, I’m here to talk about Redis.

What Redis is, how to install and other issues will not elaborate, let’s get straight to the point.

Redis five data types and application scenarios

There are five Redis data types, that is, a string, a list, hash, set, zset sort (set), I think that as long as a little to know a little bit Redis friends all should be clear. Below, we discuss the application scenarios of these five data types.

string

This type is believed to be the most familiar, but do not look down upon it, it can do a lot of things, can also lead a series of problems.

Let’s start with the simplest:

localhost:6379> set coderbear hello
OK
localhost:6379> get codebear
"hello"
Copy the code

I’m not going to explain these two commands, but let’s use strlen again:

localhost:6379> strlen codebear
(integer5)Copy the code

Oh, I see strlen this command can obtain the Value of the length, the length of the hello is 5, so the output is 5. Is this the right explanation? Take your time. Let’s take our time.

We append codebear’s key with the append command:

APPEND codebear ChinaCopy the code

What would be the output if we used the strlen command again? Of course it is 7. Although I am not good at math, I still have no problem counting up to 10. However, when we run strlen again, you will find a strange phenomenon:

localhost:6379> strlen codebear
(integer11)Copy the code

Nani, why 11? Are we opening it the wrong way? Should we try again? No, if you try it three more times, you’ll still get 11. Why is that? This brings us to binary security.

Binary security

The so-called binary security is only strictly according to the binary data access, do not attempt to parse data in a special format. Redis is binary safe. It always accesses binary data, or it can always access byte arrays.

Let’s get CodeBear Kangkang:

get codebear
"hello\xe4\xb8\xad\xe5\x9b\xbd"
Copy the code

You will notice that the “Hello China” stored in Redis actually looks like this because our Xshell client uses UTF-8. In UTF-8, one Chinese character is usually three bytes, and two Chinese characters are six bytes, so inside Redis, “Hello China” takes up 5+6=11 bytes.

If you still don’t believe me, let’s change the Xshell encoding to GBK. In the GBK world, a Chinese character usually takes two bytes, so:

localhost:6379> setCodebeargbk 中国 OK localhost:6379> get codebeargbk"\xd6\xd0\xb9\xfa"
localhost:6379> strlen codebeargbk
(integer4)Copy the code

So wake up, buddy, it is impossible to save Chinese in Redis, we can easily get Chinese in the program, only because the API does the decoding operation.

Didn’t expect a String also drew a binary security, seems can not dismiss any knowledge, which is often said that the search of hell, and when you find a problem, find the answer to this question appeared a you don’t understand something, then you began to see that you don’t understand something, and then come up to another you don’t understand the concept of, so… It’s a lot of tears.

We often use Redis as a cache, using the set get command. We can also use Redis as a second kill system. In most cases, we also use the String data type.

localhost:6379> set codebearint 5
OK
localhost:6379> incr codebearint 
(integer6)Copy the code

You may not have used the incr command before, but you can guess what the incr command does from the result and the command name.

localhost:6379> decr codebearint 
(integer5)Copy the code

It was 6, but after decr was called, it became 5 again.

Ok, one more question, String is a String, how can it add or subtract?

We use the type command to check the type of codeBearInt key:

localhost:6379> type  codebearint
string
Copy the code

Yes, it’s an exact String.

Let’s look at one more thing:

localhost:6379> object encoding codebear
"raw"
localhost:6379> object encoding codebearint
"int"
Copy the code

There is also a mark inside Redis to indicate the type of the key (which is different from the five Redis data types).

bitmap

There is a requirement: Count the number of login days in a year for a specified user. That’s not easy. I just set up a login form, and that’s it, right? Yes, it can, but isn’t that a little expensive? If you have a million users, how big is the login table? That’s when Bitmap came along, and it was a great solution to these problems.

Let’s take a look at what a bitmap is. It’s basically a binary array. Let’s draw a picture to illustrate:

This is a bitmap. It’s made up of lots and lots of little squares that can only be 1’s or 0’s. String provides a series of bitmap commands. Let’s try it out:

setbit codebear 3 1
(integer) 0
localhost:6379> get codebear
"\x10"
Copy the code

There are now 8 cells, the fourth cell has a 1 (index starts at 0), and all the other cells have zeros, like this:

Let’s calculate what the size should be, 1, 2, 4, 8, 16, yes, 16 in decimal, and we get CodeBear outputs “\x10”, “\x” means hexadecimal, which means 10 in hexadecimal is 16 in decimal.

Let’s use the strlen command again:

localhost:6379> strlen codebear
(integer1)Copy the code

Seems to take up only one byte, let’s continue:

localhost:6379> setbit codebear 5 1
(integer) 0
Copy the code

The bitmap looks like this:

The size in decimal notation is 20.

Let’s move on to Strlen:

localhost:6379> strlen codebear
(integer1)Copy the code

It’s still only one byte, we’ve already stored two bits of data, isn’t that amazing?

Let’s move on:

localhost:6379> setbit codebear 15 1
(integer) 0
localhost:6379> strlen codebear
(integer2)Copy the code

You can see from this that the bitmap is extensible, and since I’ve now put a 1 in the 16th cell, the bitmap is expanded, and now strlen is 2. So I want to know how many of these 16 cells are 1’s. What do I do? With the bitcount command:

localhost:6379> bitcount codebear
(integer) 3
Copy the code

At this point, it’s easy to use Bitmaps to count the number of days a given user logs in a year. Let’s assume codeBear logged in the first day, the second day, and the last day:

localhost:6379> setbit codebear 0 1
(integer) 0
localhost:6379> setbit codebear 1 1
(integer) 0
localhost:6379> setbit codebear 364 1
(integer) 0
localhost:6379> bitcount codebear 
(integer) 3
Copy the code

Go ahead and use Strlen to see how many bytes are accounted for on logged days throughout the year:

localhost:6379> strlen codebear
(integer46),Copy the code

It’s only 46 bytes, so even if you log in every year, it’s only 46 bytes, and I don’t know how big that data would be in a database, but I think it’s a lot more than 46 bytes, and if you have a million users, it’s less than 50 million bytes, even if those million users log in every day.

Let’s change the requirement to: Count the number of days a specified user logs in within any time window?

The bitcount command can also take two arguments, start and end:

localhost:6379> bitcount codebear 0 2
(integer2)Copy the code

We can also write the second argument as -1, representing up to the last digit, i.e. :

localhost:6379> bitcount codebear 0 -1
(integer) 3
Copy the code

The power of Bitmap goes far beyond that. Let’s take kangkang’s second requirement: To count the login status of all users in any date:

  1. The number of users who log in to the system in any day is collected
  2. The number of users who log in to the system in any days is counted
  3. The number of users who log in every day in any number of days is counted

Brain pain. Is that a fucking human thing? Don’t worry, all of this can be done with Bitmap.

The first requirement is easy to implement. Assuming that userId of user codebear is 5 and userId of user Xiaoxiao is 10, we can create a bitmap with key as date, where the fourth and ninth squares are 1, indicating that users with userId 5 and userId 1 logged in on this day. Then bitcount will do everything, as follows:

localhost:6379> setbit 20200301 4 1
(integer) 0
localhost:6379> setbit 20200301 9 1
(integer) 0
localhost:6379> bitcount 20200301
(integer2)Copy the code

To implement the following two requirements, a new command is required, and let’s look at the results:

localhost:6379> setbit 20200229 9 1
(integer) 1
localhost:6379> bitop and andResult 20200301 20200229
(integer) 2
localhost:6379> bitcount andResult
(integer) 1
localhost:6379> bitop or orResult 20200301 20200229
(integer) 2
localhost:6379> bitcount orResult
(integer2)Copy the code

First, a bitmap with key 20200229 is created. The 10th cell is 1, indicating that the user with Id 10 logged in on the day 20200229. Then, the and calculation is performed on the bitmap with key 20200301 and key 20200229. The result is also a bitmap, and the result is put into the andResult key, the following is the familiar bitcount command, how many small box 1 kangkang, the result is 1, namely these two days, every day login user has one.

Since there is and operation, then there is or operation, the following is the command of or operation, calculate these two days have two users login.

So the last two requirements are easy to handle.

There is also the famous Bloom filter is also implemented with bitmap, about bloom filter in the previous blog also introduced.

After looking at so many examples, have you noticed that all the computation is done inside Redis? For this situation, there is a very fancy term: computation moves to data. In contrast, taking data out of one place and computing it externally is called moving data to computing.

list

Redis’ list is a two-way linked list.

localhost:6379> lpush codebear a b c d e
(integer) 5
localhost:6379> lrange codebear 0 -1
1) "e"
2) "d"
3) "c"
4) "b"
5) "a"
Copy the code

L means left, lpush means left, so the first one to push is on the right, lrange starts from the left to pull out the data in the specified index range, and -1 means to get the last one.

If you can push on the left, you must be able to push on the right, kangkang:

localhost:6379> rpush codebear z
(integer) 6
localhost:6379> lrange codebear 0 -1
1) "e"
2) "d"
3) "c"
4) "b"
5) "a"
6) "z"
Copy the code

There are two other common pop-up commands that we can use:

localhost:6379> lpop codebear
"e"
localhost:6379> lrange codebear 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
5) "z"
localhost:6379> rpop codebear
"z"
localhost:6379> lrange codebear 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
Copy the code

Lpop is the first element on the left, rPOP is the first element on the right.

If we use a combination of Lpush and RPOP or Rpush and LPOP, it’s fifO, it’s a queue; If we use a combination of Lpush, LPOP or Rpush, rPOP, it’s a stack, so Redis can also be used as a message queue, using the list data type.

I believe we must have played the forum, behind the post, the post is usually in front. To performance, we can put the post data on the list of Redis, but always can’t infinite to throw the data inside the list, in general the front pages of posts through more, few people see the post back again, so we can put the front pages of post data in a list, and then set a rule, Delete data from list periodically, we can use ltrim of list, command:

localhost:6379> ltrim codebear 1 -1
OK
localhost:6379> lrange codebear 0 -1
1) "c"
2) "b"
3) "a"
Copy the code

The ltrim parameter is 1, and the second parameter is -1. If the value of ltrim is 1, the value of ltrim is 0.

hash

Now has a product detail page, there is a product introduction, price, have a warm prompt, for page, a purchase number and so on a pile of information, of course, we can use the String to the whole object storage, but there may be some places need only product introduction, although this is the case, we still have to take out the whole object, isn’t it a little less expensive? Hash can solve problems like this:

localhost:6379> hset codebear name codebear
(integer) 1
localhost:6379> hset codebear age 18
(integer) 1
localhost:6379> hset codebear sex true
(integer) 1
localhost:6379> hset codebear address suzhou
(integer) 1
localhost:6379> hget codebear address
"suzhou"
Copy the code

What if we’re storing the entire object and we want to change the age? You have to take the whole object out, and then you have to assign it, and then you have to put it back, but now:

localhost:6379> hincrby codebear age 2 
(integer) 20
localhost:6379> hget codebear age
"20"
Copy the code

set

Set is an unordered and de-duplicated data structure. We can use it to de-duplicate. For example, if I want to store the ids of all goods, I can use set to implement this. Of course, there are many implementation schemes to prevent cache penetration, and the SET scheme is just one of them. Let’s look at kangkang’s basic usage:

localhost:6379> sadd codebear 6 1 2 3 3 8 6
(integer) 5
localhost:6379> smembers codebear 
1) "1"
2) "2"
3) "3"
4) "6"
5) "8"
Copy the code

You can clearly see that the data we saved was erased, and the data was scrambled.

What does srandmember do?

localhost:6379> srandmember codebear 2
1) "6"
2) "3"
localhost:6379> srandmember codebear 2
1) "6"
2) "2"
localhost:6379> srandmember codebear 2
1) "6"
2) "3"
localhost:6379> srandmember codebear 2
1) "6"
2) "2"
localhost:6379> srandmember codebear 2
1) "8"
2) "3"
Copy the code

Srandmember can be followed by a parameter, followed by 2, which means that two elements can be randomly removed. If you want to remove two elements that can be repeated, what should you do?

localhost:6379> srandmember codebear -2
1) "6"
2) "6"
Copy the code

If it is followed by a negative number, it means that the retrieved element can be repeated.

What if the number that follows is greater than the number of set elements?

localhost:6379> srandmember codebear 100
1) "1"
2) "2"
3) "3"
4) "6"
5) "8"
localhost:6379> srandmember codebear -10
 1) "8"
 2) "1"
 3) "1"
 4) "1"
 5) "6"
 6) "1"
 7) "1"
 8) "2"
 9) "6"
10) "8"
Copy the code

If it is a positive number, at most return all the elements in the set, because the positive number is not repeated, return one more, repeat, if it is a negative number, then it does not affect how many elements, followed by several.

If we do a lottery system, we can use this command, if we can repeat the lottery, followed by a negative number, if we can’t repeat the lottery, followed by a positive number.

Set can also calculate difference sets, union sets, and intersection sets:

localhost:6379> sadd codebear1 a b c
(integer) 3
localhost:6379> sadd codebear2 a z y
(integer) 3
localhost:6379> sunion codebear1 codebear2
1) "a"
2) "c"
3) "b"
4) "y"
5) "z"
localhost:6379> sdiff codebear1 codebear2
1) "b"
2) "c"
localhost:6379> sinter codebear1 codebear2
1) "a"
Copy the code

The above command doesn’t have to be explained much, but we can use it as a recommendation system for fraudulent financing: who your mutual friends are, what games you both play, who you might know.

zset

Set is unordered, while Zset is ordered. Each element has a concept of score. The smaller the score is, the more advanced the score is.

localhost:6379> zadd codebear 1 hello 3 world 2 tree
(integer) 3
localhost:6379> zrange codebear 0 -1 withscores
1) "hello"
2) "1"
3) "tree"
4) "2"
5) "world"
6) "3"
localhost:6379> zrange codebear 0 -1
1) "hello"
2) "tree"
3) "world"
Copy the code

Now we create a zset with key codeBear and add three elements to it: Hello, world, tree, and score are 1, 3, and 2 respectively. Then we use zrange to retrieve the results and find that the score has been sorted according to the size of score. If “withscores” is followed, score will be extracted together.

If we want to see where tree is ranked, we can use zrank:

localhost:6379> zrank codebear tree
(integer1)Copy the code

And since we started at 0, it’s going to be 1.

If we want to query the score of a tree:

localhost:6379> zscore codebear tree
"2"
Copy the code

What if we want to take out the first two from the largest to the smallest:

localhost:6379> zrange codebear -2 -1
1) "tree"
2) "world"
Copy the code

But there is something wrong with this result. What about the first two elements from largest to smallest, the first element being world:

localhost:6379> zrevrange codebear 0 1
1) "world"
2) "tree"
Copy the code

Things like leaderboards, hot data, and deferred task queues can all be implemented with ZSet, which I’ve covered in my previous blog.

Speaking of SZet, it might also raise the question, what is zset implemented in Redis? Jump table.

As for the skip table, I will not expand it here, why to use the skip table implementation, because the characteristics of the skip table: read and write balancing.

Why is Redis so fast

This is a classic interview question. Almost 80% of interviews will ask this question when talking about Redis. Why is Redis so fast? The main reasons are as follows:

  1. Programming language: Redis is written in C language, closer to the bottom, you can directly call OS functions.
  2. Memory based: Because Redis data is stored in memory, it is faster. If placed on a hard disk, performance depends on two metrics: addressing (rotational speed) and throughput. Addressing is at the millisecond level, generally around 500M, even if the server performance is very good, there will not be a few gigabytes of throughput, but in memory, it is nanosecond level.
  3. Single-threaded: Because Redis is single-threaded, it avoids the cost of thread switching, and there is no contention, so it is faster.
  4. Network model: Because the network model of Redis is epoll, it is a multiplexed network model. (More on epoll later)
  5. Redis data structure optimization: 5 data types are provided in Redis, among which Zset is optimized with hop tables, and the whole Redis is actually optimized with hash, so that its time cost is O(1) and lookup is faster.
  6. Redis6.0 comes out with I/O Threads, so it’s faster. (I/O Threads will be discussed later)

What are the disadvantages of Redis

This is an open-ended question with many answers, such as:

  1. Because Redis is single-threaded, it can’t take advantage of multi-core cpus.
  2. Because Redis is single-threaded, once a complex command is executed, all subsequent commands are blocked at the door.
  3. Unable to add expiration time to an entry in the hash.

Why does Redis guarantee atomicity

Because Redis is single-threaded, only one read/write request can be processed at a time, so atomicity is guaranteed.

Redis is single-threaded, how to explain it

We keep saying that Redis is single-threaded, Redis is single-threaded, but is Redis really single-threaded at all? Redis is a single thread, so there is only one work thread in Redis.

What are I/O Threads

I/O Threads is a new feature in Redis 6.0. Previously, Redis received requests from the socket, processed them, and wrote the results to the socket serialized.

After Redis6.0 introduced I/O Threads:

What is the epoll

Epoll is a multiplexed IO model. Before we talk about Epoll, we have to talk about the traditional IO model. The traditional IO model is synchronous blocking. That is, the socket set up by the server will wait for the client to connect, and then wait for the client to write the request. A server can only serve one client.

Later, programmers found that they could solve this problem with multithreading:

  1. When the first client connects to the server, the server starts the first thread, and the interaction between the first client and the server takes place in the first thread.
  2. When the second client connects to the server, the server starts the second thread, and the interaction between the second client and the server takes place in the second thread.
  3. When the third client connects to the server, the server starts a third thread, and the interaction between the third client and the server takes place in the third thread.

In Java, threads have their own stack. One thread consumes at least 1M, and the CPU will not be able to handle unlimited threads.

Although it took several times to come to the era of epoll, as a Curd boy and API boy, I will not go so deep into the study. Now let’s skip the middle era and go directly to the era of epoll.

Let’s start with the epoll method. In Linux, we can use man to look at OS functions:

man epoll
Copy the code

In the introduction there is this passage:

       *  epoll_create(2) creates a new epoll instance and returns a file descriptor referring to that instance.  (The more recent epoll_create1(2) extends
          the functionality of epoll_create(2).)

       *  Interest in particular file descriptors is then registered via epoll_ctl(2).  The set of  file  descriptors  currently  registered  on  an  epoll
          instance is sometimes called an epoll set.

       *  epoll_wait(2) waits for I/O events, blocking the calling thread if no events are currently available.
Copy the code

Although my English is really poor, but with the help of the translation, I can barely understand some, roughly meaning:

  1. Epoll_create creates an epoll example and returns a file descriptor.
  2. Epoll_ctl is used to register events of interest.
  3. Epoll_wait is used to wait for I/O events and blocks if there are no I/O events of interest. The implication is that this method will return if an interesting event occurs.

Here’s a demo, let’s try it out:

epollfd = epoll_create1(0); // Create an epoll instance that returns an epoll file descriptorif (epollfd == -1) {
               perror("epoll_create1");
               exit(EXIT_FAILURE); } ev.events = EPOLLIN; ev.data.fd = listen_sock; // Register the event of interest // The first parameter is epoll file descriptor // the second parameter is action, now it is time to add the event of interest // the third parameter is listened file descriptor // the fourth parameter tells the kernel what event to listen for // Now the event is EPOLLIN, Indicates that there is readable data on the corresponding file descriptorif (epoll_ctl(epollfd, EPOLL_CTL_ADD, listen_sock, &ev) == -1) {
               perror("epoll_ctl: listen_sock");
               exit(EXIT_FAILURE); } // An infinite loopfor(;;) {// Wait for IO events to occur // The first argument is the epoll file descriptor // The second argument is the set of events that occurred // The third argument is not important // the fourth argument is the wait time, NFDS = epoll_wait(epollfd, events, MAX_EVENTS, -1); NFDS = epollfd, events, MAX_EVENTS, -1);if (nfds == -1) {
                   perror("epoll_wait");
                   exit(EXIT_FAILURE); } / / cyclefor(n = 0; n < nfds; ++n) {// If the file descriptor corresponding to the event is listen_sockif(n].data.fd == listen_sock) {// Establish connection. Conn_sock = accept(listen_sock, (struct sockaddr *) &addr, &addrlen);if (conn_sock == -1) {
                           perror("accept");
                           exit(EXIT_FAILURE); } setnonblocking(conn_sock); / / set non-blocking ev. Events = EPOLLIN | EPOLLET; // Set ev.data.fd = conn_sock; // Add the event of interest as EPOLLIN or EPOLLETif (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock,
                                   &ev) == -1) {
                           perror("epoll_ctl: conn_sock");
                           exit(EXIT_FAILURE); }}else{ do_use_fd(events[n].data.fd); }}}Copy the code

Because I have not learned C language, some notes wrong place please excuse me, but I think it is probably so meaning.

If you have studied NIO in Java, the code above should look similar.

Epoll tells the kernel which events I am interested in, and the kernel will listen for you. When an event of interest occurs, the kernel will actively notify you.

What are the advantages of this:

  1. Reduce switching between user and kernel modes.
  2. Event-based readiness notification: the kernel actively notifies you before you bother to poll or judge.
  3. File descriptors have almost no upper limit: you can interact with as many clients as you want, and a thread can listen to N clients and complete the interaction.

The epoll function is os-based. In Windows, there is no such thing as epoll.

Well, that’s it for epoll. There are three new terms: user state, kernel state, and file descriptor, but I won’t explain them until I write NIO’s blog. At that time, epoll will be covered in more detail.

Redis expiration policy

Generally speaking, there are three expiration strategies commonly used:

  1. Scheduled deletion: You need to add a timer for each key to remove data when it expires. The advantage is that it is very accurate, but the disadvantage is that it consumes a lot of energy.
  2. Periodic deletion: Every once in a while, a certain number of keys are scanned and data is removed if they are out of date. The advantage is that the consumption is small, but the disadvantage is that expired keys cannot be removed in time.
  3. Lazy deletion: Before using a key, check whether the key expires and delete it. The advantage is that the consumption is small, but the disadvantage is that the expired key cannot be removed in time. It will be removed only when used.

Redis uses a strategy of periodic deletion + lazy deletion.

The pipe

If we have a lot of commands to send to Redis, the first solution is to send them one by one, which has obvious disadvantages: each command needs to pass through the network and the performance is relatively low. The second solution is to use pipes. Before we get into pipes, let’s demonstrate one thing:

[root@localhost ~]# nc localhost 6379
set codebear hello
+OK
get codebear
A $5
hello
Copy the code

To send a command to Redis, it is not necessary to use the Redis client, just connect to the port of the Redis server. As for what $5 means after the get codeBear command, I will not discuss here.

How to use the pipe in the end, with the above foundation, it is actually very simple:

[root@localhost ~]# echo -e "set codebear hello1234 \n incr inttest \n set haha haha" | nc localhost 6379
+OK
:1
+OK
Copy the code

Commands are separated with \n and sent to Redis via NC.

Let’s see if Kangkang succeeded:

[root@localhost ~]# nc localhost 6379
get inttest
The $1
1
get codebear
$9
hello1234
get haha
$4
haha
Copy the code

Note that although multiple commands are sent together, they do not have atomicity as a whole. The major Redis components also provide a way to pipe, so try it the next time you need to send multiple commands in a project.

Release subscription

When we have a message that needs to be pushed to each system in the form of broadcast, in addition to the message queue, we can also use the way of publish and subscribe. Redis provides the function of publish and subscribe. Let’s see how to use it.

First, we create a subscriber to a channel named Hello:

localhost:6379> subscribe hello
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "hello"(3)integer1)Copy the code

Next, create a publisher to send a message to a channel named Hello:

localhost:6379> publish hello goodmorning
(integer1)Copy the code

Finally, back to the subscriber, we find that we have received a message:

1) "message"
2) "hello"
3) "goodmorning"
Copy the code

However, it should be noted that if the subscriber publishes the message first and then subscribes, it will not receive the historical message.

Isn’t it very simple? Before I knew ZooKeeper, I thought Redis could be used as the configuration center with publish and subscribe function.

Out of memory

If Redis is running out of memory and can no longer accommodate new data, the Redis memory flushing policy is triggered.

maxmemory-policy volatile-lru
Copy the code

It has several configurations, before talking about the specific configuration, to say two nouns, if the two nouns do not understand, then the meaning of each configuration is really only rote memorization.

  • LRU: Least-used elimination algorithm: If this key is rarely used, it is eliminated
  • LFU: Not recently used elimination algorithm: If this key has not been used recently, it is eliminated

The following is the specific configuration, we look at one by one:

  • Volatile -lru: Removes the least recently used key from the key whose expiration time is set
  • Allkeys-lru: removes the least recently used key of allkeys
  • Volatile -lfu: Removes the recently unused key from the key whose expiration time is set
  • Allkeys-lfu: removes the recently unused key from allkeys
  • Volatile -random: Randomly removes a key from a key whose expiration time is set
  • Allkeys-random: deletes a key randomly
  • Volatile – TTL: In a key space with an expiration time set, the key with an earlier expiration time is removed first
  • -sheldon: Do you want to throw an exception without doing anything

Which configuration should you use in a production environment? It can be said that online answers vary, but one thing that can be iction is that noeviction will not be chosen in general, so this question is preferred with the pantheon answer, a perfectly correct nonsense answer: look at the scene.

There are still a lot of things I haven’t mentioned in this blog. I don’t mention persistence, transactions, protocols, modules, GEO, hyperLogLog, etc. I also don’t mention the extension of Redis — cache breakdown, cache avalanche, cache penetration, etc. We’ll talk about it later.