Heim >Datenbank >Redis >Lernen Sie gemeinsam die Prinzipien und Lösungen der Redis-Cache-Penetration, Cache-Aufschlüsselung und Cache-Lawine kennen

Lernen Sie gemeinsam die Prinzipien und Lösungen der Redis-Cache-Penetration, Cache-Aufschlüsselung und Cache-Lawine kennen

coldplay.xixi
coldplay.xixinach vorne
2021-01-28 18:13:132402Durchsuche

Lernen Sie gemeinsam die Prinzipien und Lösungen der Redis-Cache-Penetration, Cache-Aufschlüsselung und Cache-Lawine kennen

Empfohlen (kostenlos): redis

  • Cache-Penetration: Die entsprechenden Cache-Daten im Schlüssel sind nicht vorhanden, was zu einer Anforderung an die Datenbank führt, wodurch sich der Druck auf die Datenbank verdoppelt

  • Cache-Aufschlüsselung: Im Moment nach Ablauf von Redis fordern viele Benutzer dieselben zwischengespeicherten Daten an, was dazu führt, dass diese Anforderungen alle die Datenbank anfordern, wodurch sich der Datenbankdruck für einen Schlüssel verdoppelt

  • Cache-Lawine: Der Cache-Server ist ausgefallen oder eine große Anzahl von Caches ist in einem bestimmten Zeitraum konzentriert, wodurch alle Anforderungen an die Datenbank gesendet werden, wodurch sich der Datenbankdruck verdoppelt. Dies gilt für mehrere Schlüssel 1. Lösung für die Cache-Penetration

Die übliche Methode kann darin bestehen, die Bloom-Filtermethode zum Abfangen von Daten zu verwenden. Zweitens gibt es eine andere Lösung, nämlich wenn die angeforderten Daten vorhanden sind leer, der leere Wert wird ebenfalls nicht zwischengespeichert. Das heißt, wenn ein Schlüssel abläuft, gehen mehrere Anfragen ein, um einer der Anfragen den Betrieb der Datenbank zu ermöglichen, und andere Anfragen warten darauf, dass die erste Anfrage das Ergebnis erfolgreich zurückgibt, bevor sie erneut anfordern.

<?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;
    }
}
    3. Lösung zum Cachen von Lawinen
  • 常用方法可以采用布隆过滤器方法进行数据拦截,其次可以还有一种解决思路,就是如果请求的数据为空,将空值也进行缓存,就不会发生穿透情况
<?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;
    }
}

二、缓存击穿解决办法

  • 使用互斥锁(mutex key),就是一个key过期时,多个请求过来允许其中一个请求去操作数据库,其他请求等待第一个请求成功返回结果后再请求。
<?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;
    }
}

三、缓存雪崩的解决办法

  • 这种情况是因为多个key同时过期导致的数据库压力,一种方法可以在key过期时间基础上增加时间随机数,让过期时间分散开,减少缓存时间过期的重复率
  • 另一种方法就是加锁排队,这种有点像上面缓存击穿的解决方式,但是这种请求量太大,比如5000个请求过来,4999个都需要等待,这必然是指标不治本,不仅用户体验性差,分布式环境下就更加复杂,因此在高并发场景下很少使用
  • 最好的解决方法,是使用缓存标记,判断该标记是否过期,过期则去请求数据库,而缓存数据的过期时间要设置的比缓存标记的长,这样当一个请求去操作数据库的时候,其他请求拿的是上一次缓存数据
Diese Situation wird durch den Datenbankdruck verursacht, der dadurch verursacht wird, dass mehrere Schlüssel gleichzeitig ablaufen Fügen Sie eine zeitliche Zufallszahl hinzu, die auf der Ablaufzeit des Schlüssels basiert, um die Ablaufzeit zu verteilen und die Wiederholungsrate des Ablaufs der Cache-Zeit zu verringern.🎜🎜Eine andere Methode besteht darin, zu sperren und in die Warteschlange zu stellen. Das ist ein bisschen wie die oben beschriebene Lösung, aber die Anzahl der Anfragen ist zu groß. Es gehen beispielsweise 5.000 Anfragen ein und 4.999 Anfragen müssen warten. Dies muss ein Indikator sein, der die Grundursache nicht behebt Nur die Benutzererfahrung ist schlecht, aber in einer verteilten Umgebung ist es noch komplizierter. Daher wird es selten in Szenarien mit hoher Parallelität verwendet🎜🎜Die beste Lösung ist die Verwendung Cache-Tags, um festzustellen, ob das Tag abgelaufen ist, fordern Sie die Datenbank und den Cache an. Die Ablaufzeit der Daten sollte länger als die Cache-Markierung eingestellt werden, damit bei einer Anforderung zum Betrieb der Datenbank andere Anforderungen ausgeführt werden Holen Sie sich die letzten zwischengespeicherten Daten🎜🎜rrreee

Das obige ist der detaillierte Inhalt vonLernen Sie gemeinsam die Prinzipien und Lösungen der Redis-Cache-Penetration, Cache-Aufschlüsselung und Cache-Lawine kennen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen