This is the sixth day of my participation in Gwen Challenge

This article has participated in the weekend study program, click to see more details.

The problem started when a wechat group leader said that the code supporting SingleFlight had been changed

In the sense that programmers can have skills they don’t know and can’t have terms they don’t know, search for singleflight~ and find the term “cache breakdown” and related terms as well as cache avalanche.

concept

Let’s start with the concept of nouns:

Cache breakdown: when the hot key expires at a certain point in time, a large number of concurrent requests come to the key at this point, so that a large number of requests are called to DB [1]. The cache doesn’t work at this point, it’s like being “punctured.” A cache breakdown can cause a sudden increase in database stress.

Cache avalanche: A large amount of data in the cache reaches the expiration date, but a large amount of query data causes the database to become overloaded or even go down.

The solution

The mutex

When the cache fails, add A lock to fetch data from the database. Only one thread (thread A) can access the database while the other threads wait. When thread A successfully reads the database data, it updates the data to the cache, and other waiting threads directly read the cache to obtain the data. Go’s SingleFlight uses this idea. Let’s first post a snippet of java-Redis code:

The redis. Setnx method is locking.

Setnx, short for SET if Not eXists. Set the key value to value only if the key does not exist. If the key already exists, the SETNX command does nothing. The command returns 1 on success and 0 on failure.

String get(String key) {  
   String value = redis.get(key);  
   if (value  == null) {  
    if (redis.setnx(key_mutex, "1") = =1) {
        redis.expire(key_mutex, 3 * 60)  
        value = db.get(key);  
        redis.set(key, value);  
        redis.delete(key_mutex);  
    } else {  
        // Other threads rest for 50 ms and retry
        Thread.sleep(50); get(key); }}}Copy the code

Go’s SingleFlight uses the same mutex scheme. In the implementation, SingleFlight uses a temporary map to store the data read from the database by the first coroutine, and the subsequent methods fetch the data directly from the map without even needing to read from the cache. Singleflight full code is not much, its Github address.

The source code can be viewed at the Go installation path, such as C: Program Files Go SRC internal SingleFlight.

Asynchronous build cache

Simply put, fetch is always fetched from the cache; The cache stores data and expiration time. After each expiration, another thread is started to retrieve data and update the cache. Data consistency is not guaranteed, but in most cases it will suffice.

Bloom filter

The purpose of the Bloom filter is to quickly determine whether an element is in a set.

The application of Bloom filter to cache breakdown is to maintain a set of database keys. Each request first takes data from the cache. If there is no key in the cache, bloom filter is used to determine whether the queried key may be in the database; otherwise, the database will not be requested [3].

[1] Cache breakdown – Baidu Encyclopedia, baike.baidu.com/item/%E7%BC…

[2] silenceper.com/blog/202003…

[3] www.cnblogs.com/wangwust/p/…