Home  >  Article  >  Database  >  Learn together the principles and solutions of Redis cache penetration, cache breakdown, and cache avalanche

Learn together the principles and solutions of Redis cache penetration, cache breakdown, and cache avalanche

coldplay.xixi
coldplay.xixiforward
2021-01-28 18:13:132310browse

Learn together the principles and solutions of Redis cache penetration, cache breakdown, and cache avalanche

Recommended (free): redis

  • Cache penetration:The corresponding cache data in the key does not exist, causing the database to be requested, causing the pressure on the database to double.

  • Cache breakdown: One after redis expires Instantly, a large number of users request the same cached data, causing these requests to request the database, causing the pressure on the database to double. For a key,

  • Cache avalanche:The cache server is down or a large number of caches are concentrated in a certain period of time, causing all requests to go to the database, causing the database pressure to double. This is for multiple keys

1. Solution to cache penetration

  • Commonly used methods can use the Bloom filter method to intercept data. Secondly, there is another solution, that is, if the request The data is empty, and the empty values ​​are also cached, so that penetration will not occur
<?php
class getPrizeList {
    /**
     * redis实例
     * @var \Redis
     */
    private $redis;

    /**
     * @var string
     */
    private $redis_key = &#39;|prize_list&#39;;

    /**
     * 过期时间
     * @var int
     */
    private $expire = 30;

    /**
     * getPrizeList constructor.
     * @param $redis
     */
    public function __construct($redis)
    {
        $this->redis = $redis;
    }

    /**
     * @return array|bool|string
     */
    public function fetch()
    {
        $result = $this->redis->get($this->redis_key);
        if(!isset($result)) {
            //此处应该进行数据库查询...
            //如果查询结果不存在,给其默认空数组进行缓存
            $result = [];
            $this->redis->set($this->redis_key, $result, $this->expire);
        }

        return $result;
    }
}

2. Cache breakdown solution

  • Using a mutex key means that when a key expires, multiple requests come to allow one of the requests to operate the database, and other requests wait for the first request to successfully return the result before requesting again.
<?php
class getPrizeList {
    /**
     * redis实例
     * @var \Redis
     */
    private $redis;

    /**
     * @var string
     */
    private $redis_key = &#39;|prize_list&#39;;

    /**
     * @var string
     */
    private $setnx_key = &#39;|prize_list_setnx&#39;;

    /**
     * 过期时间
     * @var int
     */
    private $expire = 30;

    /**
     * getPrizeList constructor.
     * @param $redis
     */
    public function __construct($redis)
    {
        $this->redis = $redis;
    }

    /**
     * @return array|bool|string
     */
    public function fetch()
    {
        $result = $this->redis->get($this->redis_key);
        if(!isset($result)) {
            if($this->redis->setnx($this->setnx_key, 1, $this->expire)) {
                //此处应该进行数据库查询...
                //$result = 数据库查询结果;
                $this->redis->set($this->redis_key, $result, $this->expire);
                $this->redis->del($this->setnx_key); //删除互斥锁
            } else {
                //其他请求每等待10毫秒重新请求一次
                sleep(10);
                self::fetch();
            }
        }

        return $result;
    }
}

3. Solution to cache avalanche

  • This situation is caused by multiple keys expiring at the same time. Database pressure, one method can be to add a time random number based on the key expiration time, so that the expiration time is spread out, and the repetition rate of cache time expiration is reduced.
  • Another method is to lock Queuing is a bit like the solution to cache breakdown above, but the amount of requests is too large. For example, 5,000 requests come in, and 4,999 requests have to wait. This must be an indicator that does not cure the root cause. Not only is the user experience poor, but also in a distributed environment. It is more complicated, so it is rarely used in high concurrency scenarios.
  • The best solution is to use a cache tag to determine whether the tag has expired. If it expires, request the database, and cache The expiration time of the data should be set longer than the cache mark, so that when a request is made to operate the database, other requests will get the last cached data
<?php
class getPrizeList {
    /**
     * redis实例
     * @var \Redis
     */
    private $redis;

    /**
     * @var string
     */
    private $redis_key = &#39;|prize_list&#39;;

    /**
     * 缓存标记key
     * @var string
     */
    private $cash_key = &#39;|prize_list_cash&#39;;

    /**
     * 过期时间
     * @var int
     */
    private $expire = 30;

    /**
     * getPrizeList constructor.
     * @param $redis
     */
    public function __construct($redis)
    {
        $this->redis = $redis;
    }

    /**
     * @return array|bool|string
     */
    public function fetch()
    {
        $cash_result = $this->redis->get($this->cash_key);
        $result = $this->redis->get($this->redis_key);
        if(!$cash_result) {
            $this->redis->set($this->cash_key, 1, $this->expire);
            //此处应该进行数据库查询...
            //$result = 数据库查询结果, 并且设置的时间要比cash_key长,这里设置为2倍;
            $this->redis->set($this->redis_key, $result, $this->expire * 2);
        }

        return $result;
    }
}

The above is the detailed content of Learn together the principles and solutions of Redis cache penetration, cache breakdown, and cache avalanche. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:csdn.net. If there is any infringement, please contact admin@php.cn delete