[actual combat problems] – differences and solutions of cache penetration, cache breakdown and cache avalanche

Time:2021-4-21

Usually, we use the cache scheme, which generally stores one copy in the database and synchronously stores one copy in the cache. When the request comes, you can get the data from the cache first. If there is data, you can directly return the result in the cache. If there is no data in the cache, go to the database to retrieve the data, update it to the cache at the same time, and return the result. If there is no data in the database, you can return null directly.

There are several common problems about caching

Cache penetration

Cache penetration refers to,Data that neither cache nor database hasFor example, the order number cannot be-1, but the user requested a large number of-1Because the data does not exist, the cache will not exist, and all requests will directly penetrate into the database.
If it is used by malicious users, crazy requests for nonexistent data will lead to excessive pressure on the database, or even collapse.

Note: penetration means that there is no direct way to the database.

How can we solve this situation?

  1. Interface increases business levelFilter, which can effectively intercept most illegal requests.
  2. As a supplement to the first point, the most common method is to use bloom filter to hash the possible data value into bitmap for one or more dimensions. If bitmap proves that the data does not exist, the data must not exist. However, bitmap proves that the data can only exist, because the bit from different hash values is likely to be the same, and hash conflict will lead to Misjudgment, multiple hash methods can only reduce the probability of conflict, can not be avoided.
  3. Another common method is to cache the empty results for the data that the database and cache do not have, but the expiration time is set to be shorter, generally within five minutes. For this kind of data, if the database is written or updated, the cache must be refreshed at the same time, otherwise it will lead to inconsistency.

Buffer breakdown

Cache breakdown refers to the fact that the database originally has data, but it is not in the cache. Generally, the cache fails suddenly. At this time, if a large number of users request the data, but the cache does not, they will go to the database to request, which will increase the pressure of the database and may be destroyed instantly.

For this kind of problem, there are generally the following methods:

  1. If it’s hot data, you can consider setting never to expire.
  2. If the data is bound to expire, then you need to set a mutually exclusive lock when the data is empty. Only one request can pass, and only one request can go to the database to pull the data. After fetching the data, you need to release the lock anyway. In case of exception, you also need to release the lock, otherwise other threads will not get the lock all the time.

The following is how to write mutex when the cache breaks down. Note: after obtaining the lock, no matter whether the operation succeeds or fails, the lock should be released. For other requests, if the lock is not obtained, they should wait and try again. Of course, if you need to be more comprehensive, you should add a number of waiting times, such as in 1s, that is, five times of sleep. When you reach this threshold, you will directly return to null. You should not consume too much machine to avoid hanging up the whole application server in an unavailable scenario.

public static String getProductDescById(String id) {
        String desc = redis.get(id);
        //The cache is empty and expired
        if (desc == null) {
            //  Mutex, only one request can succeed
            if (redis.setnx(lock_id, 1, 60) == 1) {
                try {
                    //Fetching data from a database
                    desc = getFromDB(id);
                    redis.set(id, desc, 60 * 60 * 24);
                } catch (Exception ex) {
                    LogHelper.error(ex);
                } finally {
                    //  Make sure you delete it last and release the lock
                    redis.del(lock_id);
                    return desc;
                }
            } else {
                //Otherwise, sleep for 200ms, and then acquire the lock
                Thread.sleep(200);
                return getProductDescById(id);
            }
        }
    }

Cache avalanche

Cache avalanche means that there is a large amount of data in the cache. At the same time point, or within a short period of time, all of them have expired. When the request comes over, if the cache has no data, it will request the database, then the pressure of the database will suddenly increase, and if it can’t bear it, it will be down.

In view of this situation, we generally use the following scheme:

  1. If it’s hot data, you can consider setting never to expire.
  2. Unless the cache expiration time is relatively strict, we should not consider setting a fluctuating random value. For example, if the theoretical 10 minutes, then the cache time of this kind of key is added with a 1-3 minutes, and the expiration time fluctuates within 7-13 minutes, effectively preventing a large number of expiration at the same time point.
  3. Method 1 avoids the situation of valid expiration, but if all the hot data is on a redis server, it is also extremely dangerous. If there is a network problem or the redis server is down, then all the hot data will Avalanche (can’t be found), so the hot data can’t be scattered to different computer rooms, which can also effectively reduce this situation.
  4. You can also consider the dual cache mode. Database data is synchronized to cache a and B. A sets the expiration time, and B does not set the expiration time. If a is empty, read B and update the cache asynchronously, but both caches need to be updated at the same time.

For example, set the product cache time:

redis.set(id,value,60*60 + Math.random()*1000);

Summary

Cache penetration refers to data that does not exist in the database. If requests go to the database without people, cache breakdown means that the database has data, and the cache should have data, but when the cache expires suddenly, this protective barrier is broken down. Requests go to the database directly, and cache avalanche means that many caches fail at the same time, and all traffic flows into the data Database, causing great pressure on the database.

[notes]
GitHub warehouse address:https://github.com/Damaer/cod…
Note address:https://damaer.github.io/code…

[about the author]
Qin Huai, official account.Qinhuai grocery store】The author points out that the road of technology is not for a moment, even though it is slow and continuous. Personal writing direction: Java source code analysis, JDBC, mybatis, spring, redis, distributed, Jianzhi offer, leetcode, etc., carefully write every article, don’t like the title party, don’t like fancy, mostly write a series of articles, can’t guarantee that what I write is completely correct, but I guarantee that what I write is through practice or looking for information. We hope to correct the omissions or mistakes.

What did I write in 2020?

Notes on open source

I have precious time on weekdays. I can only learn to write in the evenings and weekends. Pay attention to me and let’s grow up together~