PHP之深入学习Yii2缓存Cache组件详细讲解

 更新时间:2021年7月27日 10:00  点击:1977

什么是缓存组件Cache

缓存是提升 Web 应用性能简便有效的方式。 通过将相对静态的数据存储到缓存并在收到请求时取回缓存, 应用程序便节省了每次重新生成这些数据所需的时间。

在这里插入图片描述

定义缓存组件

Yii2的缓存是通过组件Component实现的,在项目的配置文件中,配置components->cache实现对缓存组件的定义。

项目配置文件的路径为config/web.php。

在这里插入图片描述

页面缓存PageCache

作为网站来讲,Yii2的页面缓存非常便捷地将已经渲染完全的网页结果保存起来,并在一个缓存周期内不需要再次处理页面内部的控制器动作逻辑。

配置页面缓存

页面缓存的配置方式为,在控制器层Controller中配置行为behaviors,通过调用过滤器filters的方式,在进入具体页面路径action的之前,对当前key进行计算,并判断缓存是否启用enabled缓存有效期duration。

基础配置代码如下所示

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

过滤器是Yii2中的一个概念,他可以在控制器初始化的时候加载并执行,我们可以用这个特点去做一些对控制器的数据的限制,比如控制缓存、用户权限控制。

这里我们将行为名称定义为pageCache,显然名字不重要,因为有的案例中,因为不同的页面缓存规则不一样,我会定义两个页面缓存的行为。

其中only为过滤器调用action的参数,用于限制哪些路径是启用action的。

页面缓存PageCache是缓存组件Cache的一种应用

页面缓存的根本逻辑为

  1. 配置缓存组件的实现比如文件缓存yii\caching\FileCache
  2. 页面缓存封装一层Cache组件,再去调用存取逻辑

我们可以通过查看页面缓存源码vendor/yiisoft/yii2/filters/PageCache.php,我们可以在文件的第162行发现,这里调用的cache,就是对于缓存的实现。

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

自定义页面缓存过滤器

为什么我们需要自定义缓存组件呢,我归纳原因存在以下几种

  • 缓存判断逻辑过于简单或复杂,不如自己重写痛快地多
  • 缓存key生成方式不满足业务需求

那么如何自定义呢?我个人推荐最简单粗暴的方式,继承。

use yii\filters\PageCache;

class PageCacheCtInfo extends PageCache
{
	这里是内部逻辑,不需要重写的方法可以不写。
	public $checkUser = true; //可以自定义变量
}

调用方式也是跟默认的页面缓存一样,只要换上对应的类即可。

            '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,
            ],

页面缓存key的计算

根据上一个步骤,我们可以重写计算key的方式,那么之前的key计算方式是什么样的呢?

文件位置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是一个数组,数组内的元素依次是

  • 当前类名
  • varyByRoute 一般为true
  • variations 验证,这个也是配置中获取的,根据上面的配置,则是页面路径和是否为ajax

如果是项目的首页,缓存的key则为

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

如果是个详情页面,key为

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

那么,这个key到底有什么用,为什么要单独拿出来说呢?

因为我们需要单独删除某个页面缓存。

主动清理过期缓存

根据源码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;
    }

在设置缓存之前会主动调用清理缓存的方法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);
        }
    }

这里问题就出现了,$gcProbability的默认值是10,也就是说,只有0.001%的概率会在设置缓存的同时清理过期缓存。

这不就跟没有一样!

所以对于缓存来说,需要我们主动定期清理过期缓存,不然对应的存储空间就会被占满。

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

优化缓存配置

组件的cache在项目的配置文件中定义

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

这里的自由度就出现了,现在这个配置,是文件缓存,也就是不管是数据缓存还是页面缓存,都是保存在文件里的

根据源码 public $cachePath = [email protected]/cache';

缓存的文件是放在runtime/cache文件夹的

那么问题就出现了,磁盘的性能是有瓶颈的,文件读写会影响缓存性能。

目前可选的缓存有

  • yii\caching\ApcCache,APC扩展
  • yii\caching\DbCache,数据库缓存
  • yii\caching\DummyCache,假的缓存,就是现在没条件上缓存先把坑占上
  • yii\caching\FileCache,文件缓存
  • yii\caching\MemCache,使用 PHP memcache 和 memcached 扩展
  • yii\redis\Cache,redis
  • yii\caching\WinCache,使用 PHP WinCache 扩展
  • yii\caching\XCache,使用 PHP XCache扩展
  • yii\caching\ZendDataCache,使用Zend Data Cache

总结

我在本文中,通过渐进的方式,讲了如何使用Yii2的缓存组件,对于一般的使用者来讲,已经涵盖了超过九成的坑。

如果你正在学习PHP,希望你收藏这篇文章,这会对你以后有所帮助。

在这里插入图片描述

到此这篇关于PHP之深入学习Yii2缓存Cache组件详细讲解的文章就介绍到这了,更多相关PHP之深入学习Yii2缓存Cache组件内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!

相关文章

  • php中去除文字内容中所有html代码

    PHP去除html、css样式、js格式的方法很多,但发现,它们基本都有一个弊端:空格往往清除不了 经过不断的研究,最终找到了一个理想的去除html包括空格css样式、js 的PHP函数。...2013-08-02
  • IDEA中的clean,清除项目缓存图文教程

    这篇文章主要介绍了IDEA中的clean,清除项目缓存图文教程,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-09-25
  • PHP中func_get_args(),func_get_arg(),func_num_args()的区别

    复制代码 代码如下:<?php function jb51(){ print_r(func_get_args()); echo "<br>"; echo func_get_arg(1); echo "<br>"; echo func_num_args(); } jb51("www","j...2013-10-04
  • PHP编程 SSO详细介绍及简单实例

    这篇文章主要介绍了PHP编程 SSO详细介绍及简单实例的相关资料,这里介绍了三种模式跨子域单点登陆、完全跨单点域登陆、站群共享身份认证,需要的朋友可以参考下...2017-01-25
  • php微信公众账号开发之五个坑(二)

    这篇文章主要为大家详细介绍了php微信公众账号开发之五个坑,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2016-10-02
  • PHP实现创建以太坊钱包转账等功能

    这篇文章主要介绍了PHP实现创建以太坊钱包转账等功能,对以太坊感兴趣的同学,可以参考下...2021-04-20
  • ThinkPHP使用心得分享-ThinkPHP + Ajax 实现2级联动下拉菜单

    首先是数据库的设计。分类表叫cate.我做的是分类数据的二级联动,数据需要的字段有:id,name(中文名),pid(父id). 父id的设置: 若数据没有上一级,则父id为0,若有上级,则父id为上一级的id。数据库有内容后,就可以开始写代码,进...2014-05-31
  • python怎么删除缓存文件

    在本篇文章里小编给大家整理的是一篇关于python删除缓存文件方法,需要的朋友们可以学习下。...2020-07-19
  • IIS7、iis7.5中禁止缓存单个静态文件的配置方法

    这篇文章主要介绍了IIS7、iis7.5中禁止缓存单个静态文件的配置方法,需要的朋友可以参考下...2017-07-06
  • golang与php实现计算两个经纬度之间距离的方法

    这篇文章主要介绍了golang与php实现计算两个经纬度之间距离的方法,结合实例形式对比分析了Go语言与php进行经纬度计算的相关数学运算技巧,需要的朋友可以参考下...2016-07-29
  • thinkPHP中多维数组的遍历方法

    这篇文章主要介绍了thinkPHP中多维数组的遍历方法,以简单实例形式分析了thinkPHP中foreach语句的使用技巧,需要的朋友可以参考下...2016-01-12
  • @CacheEvict + redis实现批量删除缓存

    [email protected] + redis实现批量删除缓存方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-10-12
  • PHP如何通过date() 函数格式化显示时间

    这篇文章主要介绍了PHP如何通过date() 函数格式化显示时间,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-11-13
  • php switch 与 if else 区别

    在php中switch是选择,if else也有同理,但是它们肯定是有区别的,那么我们来看看它们两者的区别在哪里呢,下面先看switch case语句吧。 switch($id){ case 1: ...2016-11-25
  • php判断邮箱地址是否存在的方法

    这篇文章主要介绍了php判断邮箱地址是否存在的方法,php判断邮箱地址是否存在的方法有两种,感兴趣的朋友可以参考一下...2016-02-18
  • PHP正则表达式过滤html标签属性(DEMO)

    这篇文章主要介绍了PHP正则表达式过滤html标签属性的相关内容,实用性非常,感兴趣的朋友参考下吧...2016-05-06
  • 详解PHP的Sodium加密扩展函数

    Sodium 出现的目的也是为了代替Mcrypt这个原来的加密扩展。在 PHP7.2 之后,Mcrypt已经被移除,在PHP7.1时就已经被标记为过时。不过,Sodium扩展的应用也并不是很多,大部分情况下我们都会使用OpenSSL来进行加密操作,所以,我们这篇文章只做了解即可。...2021-06-17
  • php图片添加文字水印实现代码

    这篇文章主要为大家详细介绍了php图片添加文字水印实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2016-03-17
  • php回溯算法计算组合总和的实例代码

    在本篇文章里小编给大家整理的是一篇关于php回溯算法计算组合总和的实例代码,有需要的朋友们可以学习参考下。...2021-07-14
  • thinkphp自定义权限管理之名称判断方法

    下面小编就为大家带来一篇thinkphp自定义权限管理之名称判断方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2017-04-03