PHP+Redis résout le problème réel de la panne du cache

藏色散人
Libérer: 2023-04-10 21:08:02
avant
3645 Les gens l'ont consulté

Recommandations associées : "PHP+Redis résout 订单限流 problèmes pratiques"

PHP+Redis résout des problèmes pratiques : panne de cache

1. Chaque numéro de cette série d'articles résoudra un problème pratique de Redis
2 Les questions de chaque numéro seront sélectionnées à partir des commentaires de chaque numéro
3 Les questions sont limitées à Redis. dans d'autres questions, je n'exclurai pas d'en ouvrir de nouvelles. Série
4 J'utilise souvent PHP, donc la solution est principalement PHP
5 Lorsqu'il n'y a pas de questions appropriées dans les commentaires, je me poserai des questions

. Description du problème :

C'est le deuxième problème, j'ai quand même posé ma propre question [Dog Head]

Comment PHP+Redis peut facilement éviter une panne de cache

Solution :

<?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;
    }
Copier après la connexion

Interprétation du code :

  • L'ontologie des données n'expire jamais

  • Paramètres Le délai d'expiration du verrou Lorsque le verrou expire, l'utilisateur qui a saisi le verrou actualisera les données

  • L'utilisateur qui n'a pas saisi le verrou. le verrou reviendra directement s'ils obtiennent les données (à ce moment, les données sont déjà des données expirées, si les exigences d'actualité des données sont élevées) Vous devez modifier le code vous-même)

  • Si l'utilisateur qui n'a pas saisi le verrou le fait n'obtient pas les données, il sera jugé chaque seconde si l'utilisateur qui a saisi le verrou a terminé l'exécution

  • Le verrou a une très faible probabilité de devenir une impasse, il est préférable d'avoir une minuterie. Les tâches sont traitées régulièrement, comme éliminer les blocages pendant les périodes de faible activité chaque jour

Apprentissage recommandé : "Tutoriel vidéo PHP"

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:learnku.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!