• 首页   /  職場   /  
  • 推薦:《PHP視頻教程》《redis教程》

    php redis 實現全頁緩存系統

    之前的一個項目說的一個功能,需要在後台預先存入某個頁面信息放到數據庫,比如app的註冊協議,用戶協議,這種.然後在寫成一個php頁面,app在調用接口的時候訪問這個頁面.當時我就發現一個問題,這些協議往往幾個月才會修改一次,而每一次用戶查看這些協議的時候,nginx都會重新從數據庫讀取文件,速度會很慢慢了.

    如下圖m_about.php是我生成的數據頁,


    企業微信截圖_15998021311479.png

    在虛擬機環境下從數據庫加載出來重新生成文件需要2.4s(當然實際的測試環境會快一點).

    既然這種頁面數據都是更新少,為什麼不緩存起來呢,想到之前看的redis常用應用裡面有一個全頁緩存系統(full page cache).不如寫一個試試看.

    代碼思路

    redis使用的是phpredis擴展,當然你也可是用predis擴展,只不過需要更改裡面幾個讀取函數而已.

    關於緩存系統的接口,我這裡參考了laravel裡面cache系統.這個系統的設計接口我覺得設置的很清晰,裡面不只是包含redis,還可以使用文件,mysql,memcache.

    當然全頁緩存用不到那麼多東西.只是借用他的函數設計.首先是函數getUrlText,這個是獲取全頁面的數據,這裡沒有想到太多,直接使用file_get_contents,當然你也可以改寫成curl函數

    /**
         * 獲取對應的url的信息
         * @param string $url 對應的地址
         * @return boolean|string
         */
        public functiоn getUrlText($url)
        {
            if (empty($url)) {
                return false;
            }
            return  file_get_contents($url);
    
        }

    其次是幾個借鑒cache系統的函數,remember函數,記憶緩存,這個是對外的最重要的接口,一般在緩存系統裡面直接使用它就好.

    /**
       * 記錄對應的緩存,如果之前存在則返回原本的緩存
       * @param string $cacheName 緩存名
       * @param string | callback $urlOrCallback 需要緩存的數據地址.可以是一個 網頁地址也一個可回調類型,如果不是可回調類型,則判定是一個網址
       * @param null | int $ttl 緩存過期時間,如果不過期就是用默認值null
       * @throws \Exception 如果無法訪問地址
       * @return boolean|string 緩存成功返回獲取到的頁面地址
       */
      public functiоn remember($cacheName, $urlOrCallback, $ttl = null)
      {
          $value = $this->get($cacheName);//檢查緩存是否存在
          if (!$value) {
              //之前沒有使用鍵
              if (is_callable($urlOrCallback)) {
                  $text = $urlOrCallback();
              } else {
                  //如果不是回調類型,則嘗試讀取網址
                  $text = $this->getUrlText($urlOrCallback);
              }
    
              if (empty($text)) {
                  throw new \Exception('can not get value:' . $urlOrCallback);
              }
              $this->put($cacheName, $text, $ttl);
              return $text;
          } else {
              return $value;
          }
    
      }

    refresh函數,刷新緩存函數,如果緩存頁面被更新了,就去刷新它.

    /**
     * 更新緩存,並返回當前的緩存
     * @param string $cacheName 緩存名
     * @param string | callback $urlOrCallback 需要緩存的數據地址.可以是一個 網頁地址也一個可回調類型,如果不是可回調類型,則判定是一個網址
     * @param null | int $ttl 過期時間,如果不過期就是用默認值null
     * @return boolean|string 緩存成功返回獲取到的頁面地址
     */
    public functiоn refresh($cacheName, $urlOrCallback, $ttl = null)
    {
        $this->delete($cacheName);
        return $this->remember($cacheName, $urlOrCallback, $ttl);
    }

    剩下的兩個代碼文件.一個是redisFPC.php,這是全頁緩存的demo,一個是測試用的文件
    fpcTest.php
    這裡是用的是github,連接到我本人的git博客上面.如果連接github有問題,可以看本文最後給的完整代碼.

    測試

    我們在這裡測試,第一次加載因為需要讀取對應的m_ahout的信息,所以慢一點

    企業微信截圖_15998021867240.png

    第二次加載因為從redislimian 讀取了,所以會快的多
    企業微信截圖_1599802202828.png

    使用建議

    代碼我認為已經給了足夠多的接口了,在第一次緩存的時候使用remember函數記錄緩存,之後如果緩存變化後使用refresh函數,更新緩存即可.如果可能的話,盡量使用ttl設置緩存的過期時間.

    完整代碼

    redisFPC.php

    <?php
    namespace RedisFPC;
    class RedisFPC
    {
        /**
         * php redis的訪問類
         * @var unknown
         */
        private $redis;
    
        /**
         * 構造函數
         * @param array $redis 使用phpredis的類
         * @param 是否連接成功
         */
        public functiоn __construct($redis = [])
        {
        
            //$this->redis = $redis;
            $this->redis = new \Redis();
            return $this->redis->connect('127.0.0.1');
        }
        /**
         * 記錄對應的緩存,如果之前存在則返回原本的緩存
         * @param string $cacheName 緩存名
         * @param string | callback $urlOrCallback 需要緩存的數據地址.可以是一個 網頁地址也一個可回調類型,如果不是可回調類型,則判定是一個網址
         * @param null | int $ttl 緩存過期時間,如果不過期就是用默認值null
         * @throws \Exception 如果無法訪問地址
         * @return boolean|string 緩存成功返回獲取到的頁面地址
         */
        public functiоn remember($cacheName, $urlOrCallback, $ttl = null) 
        {
            $value = $this->get($cacheName);//檢查緩存是否存在
            if (!$value) {
                //之前沒有使用鍵
                if (is_callable($urlOrCallback)) {
                    $text = $urlOrCallback();
                } else {
                    //如果不是回調類型,則嘗試讀取網址
                    $text = $this->getUrlText($urlOrCallback);
                }
                
                if (empty($text)) {
                    throw new \Exception('can not get value:' . $urlOrCallback);
                }
                $this->put($cacheName, $text, $ttl);
                return $text;
            } else {
                return $value;
            }
            
        }
        /**
         * 獲取對應的緩存值
         * @param string $cacheName 緩存名
         * @return String | Bool,如果不存在返回false,否則返回對應的緩存頁信息
         */
        public functiоn get($cacheName)
        {
            return $this->redis->get($this->getKey($cacheName));
        }
        /**
         * 將對應的全頁緩存保存到對應redis中
         * @param string $cacheName 緩存名
         * @param string $value
         * @param null | int $ttl 過期時間,如果不過期就是用默認值null
         * @return boolean 保存成功返回true
         */
        public functiоn put($cacheName, $value, $ttl = null)    
        {
            if (is_null($ttl)) {
                return $this->redis->set($this->getKey($cacheName), $value);
            } else {
                return $this->redis->set($this->getKey($cacheName), $value, $ttl);
            }
            
        }
        /**
         * 刪除對應緩存
         * @param string $cacheName 緩存名
         */
        public functiоn delete($cacheName)
        {
            return $this->redis->delete($this->getKey($cacheName));
        }
        
        /**
         * 更新緩存,並返回當前的緩存
         * @param string $cacheName 緩存名
         * @param string | callback $urlOrCallback 需要緩存的數據地址.可以是一個 網頁地址也一個可回調類型,如果不是可回調類型,則判定是一個網址
         * @param null | int $ttl 過期時間,如果不過期就是用默認值null
         * @return boolean|string 緩存成功返回獲取到的頁面地址
         */
        public functiоn refresh($cacheName, $urlOrCallback, $ttl = null)
        {
            $this->delete($cacheName);
            return $this->remember($cacheName, $urlOrCallback, $ttl);
        }
        /**
         * 獲取對應的url的信息
         * @param string $url 對應的地址
         * @return boolean|string
         */
        public functiоn getUrlText($url)
        {
            if (empty($url)) {
                return false;
            } 
            return  file_get_contents($url);
            
        }
        /**
         * 生成全頁緩存鍵名
         * @param string $cacheName 需要緩存的名稱
         * @return string 對應的在redis中的鍵名
         */
        private functiоn getKey($cacheName)
        {
            return 'FPC:'. $cacheName;
        }
    }

    測試用的test代碼
    注意這裡的url寫的是本地的緩存url

    <?php 
    use RedisFPC\RedisFPC;
    
    require_once 'redisFPC.php';
    /* $text = file_get_contents('http://localhost:1002/m_about.php');
    var_dump($text); */
    $url = 'http://localhost:1002/m_about.php';
    
    $fpc = new RedisFPC();
    echo $fpc->remember('服務協議', $url, 60*60*24);

    以上就是php+redis實現全頁緩存系統的詳細內容!


    ————————————————