Rumah  >  Artikel  >  pembangunan bahagian belakang  >  PHP Redis menyelesaikan masalah sebenar pecahan cache

PHP Redis menyelesaikan masalah sebenar pecahan cache

藏色散人
藏色散人ke hadapan
2022-01-10 15:20:533716semak imbas

Cadangan berkaitan: "PHP Redis menyelesaikan masalah sebenar 订单限流"

PHP Redis menyelesaikan masalah sebenar: kerosakan cache

1 Setiap keluaran siri artikel ini akan menyelesaikan masalah Redis yang praktikal
2. Soalan setiap isu akan dipilih daripada komen setiap isu
3 terhad kepada Redis berkaitan, yang lain Jika soalan itu menarik minat saya, saya tidak akan menolak untuk memulakan siri baru
4. Saya sering menggunakan PHP, jadi penyelesaiannya adalah terutamanya PHP
5. Jika tiada soalan yang sesuai dalam ulasan, saya akan membuat soalan saya sendiri

Penerangan masalah:

Ini adalah isu kedua, dan Saya masih membuat soalan saya sendiri [Kepala Anjing]

Bagaimana untuk mengelakkan kerosakan cache dengan mudah dalam PHP Redis

Penyelesaian:

<?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;
    }

Tafsiran kod:

  • Isi data tidak akan tamat tempoh

  • Tetapkan masa tamat tempoh kunci kunci tamat tempoh, pengguna yang mengambil kunci akan menyegarkan semula data

  • Pengguna yang belum mengambil kunci akan kembali terus jika mereka mendapat data (data sudah tamat tempoh pada masa ini. Jika anda mempunyai keperluan yang tinggi untuk ketepatan masa data, anda perlu mengubah suai kod sendiri)

  • Tidak ditangkap Jika pengguna yang mendapat kunci tidak mendapat data, ia akan dinilai setiap saat sama ada pengguna yang mengambil kunci telah menyelesaikan pelaksanaan

  • Kunci mempunyai kebarangkalian yang sangat kecil untuk menjadi jalan buntu Sebaiknya adakan tugasan berjadual untuk memprosesnya dengan kerap sebagai menyelesaikan kebuntuan setiap hari semasa kegawatan perniagaan

Pembelajaran yang disyorkan: "Tutorial Video PHP"

Atas ialah kandungan terperinci PHP Redis menyelesaikan masalah sebenar pecahan cache. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:learnku.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam