佳木斯湛栽影视文化发展公司

主頁(yè) > 知識(shí)庫(kù) > PHP之深入學(xué)習(xí)Yii2緩存Cache組件詳細(xì)講解

PHP之深入學(xué)習(xí)Yii2緩存Cache組件詳細(xì)講解

熱門標(biāo)簽:服務(wù)器配置 科大訊飛語(yǔ)音識(shí)別系統(tǒng) 團(tuán)購(gòu)網(wǎng)站 Linux服務(wù)器 Mysql連接數(shù)設(shè)置 阿里云 電子圍欄 銀行業(yè)務(wù)

什么是緩存組件Cache

緩存是提升 Web 應(yīng)用性能簡(jiǎn)便有效的方式。 通過(guò)將相對(duì)靜態(tài)的數(shù)據(jù)存儲(chǔ)到緩存并在收到請(qǐng)求時(shí)取回緩存, 應(yīng)用程序便節(jié)省了每次重新生成這些數(shù)據(jù)所需的時(shí)間。

定義緩存組件

Yii2的緩存是通過(guò)組件Component實(shí)現(xiàn)的,在項(xiàng)目的配置文件中,配置components->cache實(shí)現(xiàn)對(duì)緩存組件的定義。

項(xiàng)目配置文件的路徑為config/web.php。

頁(yè)面緩存PageCache

作為網(wǎng)站來(lái)講,Yii2的頁(yè)面緩存非常便捷地將已經(jīng)渲染完全的網(wǎng)頁(yè)結(jié)果保存起來(lái),并在一個(gè)緩存周期內(nèi)不需要再次處理頁(yè)面內(nèi)部的控制器動(dòng)作邏輯。

配置頁(yè)面緩存

頁(yè)面緩存的配置方式為,在控制器層Controller中配置行為behaviors,通過(guò)調(diào)用過(guò)濾器filters的方式,在進(jìn)入具體頁(yè)面路徑action的之前,對(duì)當(dāng)前key進(jìn)行計(jì)算,并判斷緩存是否啟用enabled緩存有效期duration。

基礎(chǔ)配置代碼如下所示

        return [
            'pageCache' => [
                'class' => 'yii\filters\PageCache',
                'only' => ['index'],
                'variations' => [
                    '/',
                    Yii::$app->request->isAjax,
                ],
                'enabled'=>true,
                'duration' => Yii::$app->params['pageCacheDuration'],
            ],
        ];

過(guò)濾器是Yii2中的一個(gè)概念,他可以在控制器初始化的時(shí)候加載并執(zhí)行,我們可以用這個(gè)特點(diǎn)去做一些對(duì)控制器的數(shù)據(jù)的限制,比如控制緩存、用戶權(quán)限控制。

這里我們將行為名稱定義為pageCache,顯然名字不重要,因?yàn)橛械陌咐?,因?yàn)椴煌捻?yè)面緩存規(guī)則不一樣,我會(huì)定義兩個(gè)頁(yè)面緩存的行為。

其中only為過(guò)濾器調(diào)用action的參數(shù),用于限制哪些路徑是啟用action的。

頁(yè)面緩存PageCache是緩存組件Cache的一種應(yīng)用

頁(yè)面緩存的根本邏輯為

  1. 配置緩存組件的實(shí)現(xiàn)比如文件緩存yii\caching\FileCache
  2. 頁(yè)面緩存封裝一層Cache組件,再去調(diào)用存取邏輯

我們可以通過(guò)查看頁(yè)面緩存源碼vendor/yiisoft/yii2/filters/PageCache.php,我們可以在文件的第162行發(fā)現(xiàn),這里調(diào)用的cache,就是對(duì)于緩存的實(shí)現(xiàn)。

$this->cache = Instance::ensure($this->cache, 'yii\caching\CacheInterface');

自定義頁(yè)面緩存過(guò)濾器

為什么我們需要自定義緩存組件呢,我歸納原因存在以下幾種

  • 緩存判斷邏輯過(guò)于簡(jiǎn)單或復(fù)雜,不如自己重寫痛快地多
  • 緩存key生成方式不滿足業(yè)務(wù)需求

那么如何自定義呢?我個(gè)人推薦最簡(jiǎn)單粗暴的方式,繼承。

use yii\filters\PageCache;

class PageCacheCtInfo extends PageCache
{
	這里是內(nèi)部邏輯,不需要重寫的方法可以不寫。
	public $checkUser = true; //可以自定義變量
}

調(diào)用方式也是跟默認(rèn)的頁(yè)面緩存一樣,只要換上對(duì)應(yīng)的類即可。

            'pageCacheInfo' => [
                'class' => 'common\components\PageCacheCtInfo',
                'only' => ['info'],
                'enabled'=>Yii::$app->params['pageCacheEnabled'],
                'variations' => [
                    'ct/'.Yii::$app->request->pathInfo,
                    Yii::$app->request->isAjax
                ],
                'duration' => Yii::$app->params['pageCacheInfo'],
                'checkUser' = false,
            ],

頁(yè)面緩存key的計(jì)算

根據(jù)上一個(gè)步驟,我們可以重寫計(jì)算key的方式,那么之前的key計(jì)算方式是什么樣的呢?

文件位置vendor/yiisoft/yii2/filters/PageCache.php。

    /**
     * @return array the key used to cache response properties.
     * @since 2.0.3
     */
    protected function calculateCacheKey()
    {
        $key = [__CLASS__];
        if ($this->varyByRoute) {
            $key[] = Yii::$app->requestedRoute;
        }
        return array_merge($key, (array)$this->variations);
    }

這里的緩存key是一個(gè)數(shù)組,數(shù)組內(nèi)的元素依次是

  • 當(dāng)前類名
  • varyByRoute 一般為true
  • variations 驗(yàn)證,這個(gè)也是配置中獲取的,根據(jù)上面的配置,則是頁(yè)面路徑和是否為ajax

如果是項(xiàng)目的首頁(yè),緩存的key則為

['yii\filters\PageCache','','/‘,0]

如果是個(gè)詳情頁(yè)面,key為

['yii\filters\PageCach', 'xxx/info','xxx/xxx/3xxxx74.html',0 ]

那么,這個(gè)key到底有什么用,為什么要單獨(dú)拿出來(lái)說(shuō)呢?

因?yàn)槲覀冃枰獑为?dú)刪除某個(gè)頁(yè)面緩存。

主動(dòng)清理過(guò)期緩存

根據(jù)源碼vendor/yiisoft/yii2/caching/FileCache.php

    /**
     * Stores a value identified by a key in cache.
     * This is the implementation of the method declared in the parent class.
     *
     * @param string $key the key identifying the value to be cached
     * @param string $value the value to be cached. Other types (If you have disabled [[serializer]]) unable to get is
     * correct in [[getValue()]].
     * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire.
     * @return bool true if the value is successfully stored into cache, false otherwise
     */
    protected function setValue($key, $value, $duration)
    {
        $this->gc();
        $cacheFile = $this->getCacheFile($key);
        if ($this->directoryLevel > 0) {
            @FileHelper::createDirectory(dirname($cacheFile), $this->dirMode, true);
        }
        // If ownership differs the touch call will fail, so we try to
        // rebuild the file from scratch by deleting it first
        // https://github.com/yiisoft/yii2/pull/16120
        if (is_file($cacheFile)  function_exists('posix_geteuid')  fileowner($cacheFile) !== posix_geteuid()) {
            @unlink($cacheFile);
        }
        if (@file_put_contents($cacheFile, $value, LOCK_EX) !== false) {
            if ($this->fileMode !== null) {
                @chmod($cacheFile, $this->fileMode);
            }
            if ($duration = 0) {
                $duration = 31536000; // 1 year
            }

            return @touch($cacheFile, $duration + time());
        }

        $error = error_get_last();
        Yii::warning("Unable to write cache file '{$cacheFile}': {$error['message']}", __METHOD__);
        return false;
    }

在設(shè)置緩存之前會(huì)主動(dòng)調(diào)用清理緩存的方法gc()

    /**
     * Removes expired cache files.
     * @param bool $force whether to enforce the garbage collection regardless of [[gcProbability]].
     * Defaults to false, meaning the actual deletion happens with the probability as specified by [[gcProbability]].
     * @param bool $expiredOnly whether to removed expired cache files only.
     * If false, all cache files under [[cachePath]] will be removed.
     */
    public function gc($force = false, $expiredOnly = true)
    {
        if ($force || mt_rand(0, 1000000)  $this->gcProbability) {
            $this->gcRecursive($this->cachePath, $expiredOnly);
        }
    }

這里問(wèn)題就出現(xiàn)了,$gcProbability的默認(rèn)值是10,也就是說(shuō),只有0.001%的概率會(huì)在設(shè)置緩存的同時(shí)清理過(guò)期緩存。

這不就跟沒(méi)有一樣!

所以對(duì)于緩存來(lái)說(shuō),需要我們主動(dòng)定期清理過(guò)期緩存,不然對(duì)應(yīng)的存儲(chǔ)空間就會(huì)被占滿。

Yii::$app->cache->gc(true);

優(yōu)化緩存配置

組件的cache在項(xiàng)目的配置文件中定義

'components' => ['cache' => [
    'class' => 'yii\caching\FileCache',
],],

這里的自由度就出現(xiàn)了,現(xiàn)在這個(gè)配置,是文件緩存,也就是不管是數(shù)據(jù)緩存還是頁(yè)面緩存,都是保存在文件里的

根據(jù)源碼 public $cachePath = '@runtime/cache';

緩存的文件是放在runtime/cache文件夾的

那么問(wèn)題就出現(xiàn)了,磁盤的性能是有瓶頸的,文件讀寫會(huì)影響緩存性能。

目前可選的緩存有

  • yii\caching\ApcCache,APC擴(kuò)展
  • yii\caching\DbCache,數(shù)據(jù)庫(kù)緩存
  • yii\caching\DummyCache,假的緩存,就是現(xiàn)在沒(méi)條件上緩存先把坑占上
  • yii\caching\FileCache,文件緩存
  • yii\caching\MemCache,使用 PHP memcache 和 memcached 擴(kuò)展
  • yii\redis\Cache,redis
  • yii\caching\WinCache,使用 PHP WinCache 擴(kuò)展
  • yii\caching\XCache,使用 PHP XCache擴(kuò)展
  • yii\caching\ZendDataCache,使用Zend Data Cache

總結(jié)

我在本文中,通過(guò)漸進(jìn)的方式,講了如何使用Yii2的緩存組件,對(duì)于一般的使用者來(lái)講,已經(jīng)涵蓋了超過(guò)九成的坑。

如果你正在學(xué)習(xí)PHP,希望你收藏這篇文章,這會(huì)對(duì)你以后有所幫助。

到此這篇關(guān)于PHP之深入學(xué)習(xí)Yii2緩存Cache組件詳細(xì)講解的文章就介紹到這了,更多相關(guān)PHP之深入學(xué)習(xí)Yii2緩存Cache組件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:
  • Android基于SoftReference緩存圖片的方法
  • Java jvm中Code Cache案例詳解
  • Java reservedcodecachesize虛擬機(jī)參數(shù)案例詳解
  • 解析springboot整合谷歌開源緩存框架Guava Cache原理
  • 解決@Cacheable在同一個(gè)類中方法調(diào)用不起作用的問(wèn)題
  • java中Memcached的使用實(shí)例(包括與Spring整合)
  • PHP解決高并發(fā)問(wèn)題(opcache)
  • Java SoftReference類案例詳解

標(biāo)簽:萍鄉(xiāng) 蚌埠 大理 衡水 衢州 棗莊 廣元 江蘇

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《PHP之深入學(xué)習(xí)Yii2緩存Cache組件詳細(xì)講解》,本文關(guān)鍵詞  ;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 收縮
    • 微信客服
    • 微信二維碼
    • 電話咨詢

    • 400-1100-266
    万州区| 沅陵县| 德保县| 团风县| 淅川县| 凤翔县| 大邑县| 柏乡县| 沙坪坝区| 漳浦县| 孟津县| 上蔡县| 安顺市| 甘泉县| 天祝| 屏东县| 泰安市| 威远县| 凤城市| 田阳县| 勃利县| 山阴县| 寿阳县| 西丰县| 炎陵县| 通海县| 台北县| 密山市| 黄平县| 加查县| 抚宁县| 泗水县| 英德市| 蓬溪县| 海门市| 罗平县| 烟台市| 纳雍县| 吴川市| 东乌珠穆沁旗| 浠水县|