Heim >Backend-Entwicklung >PHP-Tutorial >PHP+Redis löst das eigentliche Problem des Cache-Ausfalls

PHP+Redis löst das eigentliche Problem des Cache-Ausfalls

藏色散人
藏色散人nach vorne
2022-01-10 15:20:533770Durchsuche

Verwandte Empfehlungen: „PHP+Redis löst 订单限流 praktische Probleme

PHP+Redis löst praktische Probleme: Cache-Aufschlüsselung

1. Jede Ausgabe dieser Artikelreihe wird ein praktisches Redis-Problem lösen.
2. Die Fragen zu jeder Ausgabe werden aus den Kommentaren jeder Ausgabe ausgewählt. Die Fragen beziehen sich auf Redis Bei anderen Fragen schließe ich die Eröffnung neuer Serien nicht aus
4. Die Lösung ist daher hauptsächlich PHP
5

Problembeschreibung:

Dies ist das zweite Problem, ich habe mir immer noch meine eigene Frage gestellt [Dog Head]

Wie PHP+Redis einen Cache-Ausfall leicht vermeiden kann

Lösung:

<?php

    /**
     * 防击穿缓存
     * @param string $key       缓存key
     * @param int $expire       缓存过期时间(s)
     * @param bool $refresh     是否强制刷新数据
     * @param callable $func    获取要缓存的数据的回调方法(仅支持返回类型:?string)
     * @return null|string      返回缓存的值,没有值时且没有抢到刷新权且缓存已过期时返回null
     */
    function onceCache(string $key,int $expire,bool $refresh,callable $func): ?string
    {
        //内存,注:如果是cli模式不要使用
        static $dataStatic=[];

        //读取内存
        if(isset(self::$dataStatic[$key])){
            return self::$dataStatic[$key];
        }

        //获取laravel的获取redis连接,其它框架需要修改
        $redis=Redis::connection();

        //原缓存key加后缀"lock"为锁的key
        $lockKey=$key.&#39;:lock&#39;;

        //锁是否有效
        $lock=false;

        //读取数据
        $data=$redis->get($key);

        //如果 非强制刷新 且 缓存非空 ,获取锁
        if(!$refresh && !is_null($data)){
            $lock = $redis->get($lockKey);
        }

        if(!$lock){//如果锁过期或无数据
            $lock=$redis->setnx($lockKey,1);    //仅当锁不存在时设置锁,值1代表数据获取中
            if($lock || $refresh){              //抢到新锁 或 强制刷新
                try {
                    $data=$func();              //从回调函数获取要缓存的数据

                    //有数据则写入缓存,没有则删除数据
                    if(!is_null($data)){
                        $redis->set($key,$data);
                    }else{
                        $redis->del([$key]);
                    }

                    $redis->set($lockKey,2,&#39;ex&#39;,$expire);   //设置锁的过期时间,值2代表数据获取完成
                }catch (Exception $exception){
                    $redis->del([$lockKey]);                //发生异常,删除锁
                }
            }else{
                //如果没有数据,又没有抢到锁
                //30秒内每秒判断抢到锁的用户是否执行完成,执行完成则从缓存得到数据并返回
                $retry=0;
                do{
                    sleep(1);
                    $retry++;
                    $data = $redis->get($key);
                }while(is_null($data) && $redis->get($lockKey)==1 && $retry<30);
            }
        }

        //写入内存
        if(!is_null($data)){
            $dataStatic[$key]=$data;
        }

        //返回数据
        return $data;
    }
Code-Interpretation:

Datenontologie läuft nie ab

  • Einstellungen Die Ablaufzeit der Sperre aktualisiert den Benutzer, der die Sperre ergriffen hat.

  • Der Benutzer, der die Sperre nicht ergriffen hat Die Sperre kehrt direkt zurück, wenn sie die Daten erhalten (zu diesem Zeitpunkt handelt es sich bei den Daten bereits um abgelaufene Daten, wenn die Anforderungen an die Aktualität der Daten hoch sind). Sie müssen den Code selbst ändern)

  • Wenn der Benutzer, der die Sperre nicht ergriffen hat, dies tut Wenn die Daten nicht abgerufen werden, wird jede Sekunde beurteilt, ob der Benutzer, der die Sperre ergriffen hat, die Ausführung abgeschlossen hat

  • Die Wahrscheinlichkeit, dass die Sperre zu einem Deadlock wird, ist sehr gering. Es ist am besten, einen Timer zu haben. Aufgaben werden regelmäßig verarbeitet. wie zum Beispiel das tägliche Beheben von Deadlocks während geschäftsschwacher Zeiten

  • Empfohlenes Lernen: „

    PHP-Video-Tutorial

Das obige ist der detaillierte Inhalt vonPHP+Redis löst das eigentliche Problem des Cache-Ausfalls. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

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