当前位置:首页 > CMS教程 > 其它CMS > 列表

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

发布:smiling 来源: PHP粉丝网  添加日期:2022-05-10 10:35:54 浏览: 评论:0 

这篇文章主要介绍了PHP之深入学习Yii2缓存Cache组件详细讲解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下。

什么是缓存组件Cache

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

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

定义缓存组件

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

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

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

页面缓存PageCache

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

配置页面缓存

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

基础配置代码如下所示:

  1. return [ 
  2.     'pageCache' => [ 
  3.         'class' => 'yii\filters\PageCache'
  4.         'only' => ['index'], 
  5.         'variations' => [ 
  6.             '/'
  7.             Yii::$app->request->isAjax, 
  8.         ], 
  9.         'enabled'=>true, 
  10.         'duration' => Yii::$app->params['pageCacheDuration'], 
  11.     ], 
  12. ]; 

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

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

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

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

页面缓存的根本逻辑为

配置缓存组件的实现比如文件缓存yii\caching\FileCache

页面缓存封装一层Cache组件,再去调用存取逻辑

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

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

自定义页面缓存过滤器

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

缓存判断逻辑过于简单或复杂,不如自己重写痛快地多

缓存key生成方式不满足业务需求

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

  1. use yii\filters\PageCache; 
  2.  
  3. class PageCacheCtInfo extends PageCache 
  4.     这里是内部逻辑,不需要重写的方法可以不写。 
  5.     public $checkUser = true; //可以自定义变量 

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

  1. 'pageCacheInfo' => [ 
  2.     'class' => 'common\components\PageCacheCtInfo'
  3.     'only' => ['info'], 
  4.     'enabled'=>Yii::$app->params['pageCacheEnabled'], 
  5.     'variations' => [ 
  6.         'ct/'.Yii::$app->request->pathInfo
  7.         Yii::$app->request->isAjax 
  8.     ], 
  9.     'duration' => Yii::$app->params['pageCacheInfo'], 
  10.     'checkUser' = false, 
  11. ], 

页面缓存key的计算

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

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

  1. /** 
  2.  * @return array the key used to cache response properties. 
  3.  * @since 2.0.3 
  4.  */ 
  5. protected function calculateCacheKey() 
  6.     $key = [__CLASS__]; 
  7.     if ($this->varyByRoute) { 
  8.         $key[] = Yii::$app->requestedRoute; 
  9.     } 
  10.     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

  1. /** 
  2.  * Stores a value identified by a key in cache. 
  3.  * This is the implementation of the method declared in the parent class. 
  4.  * 
  5.  * @param string $key the key identifying the value to be cached 
  6.  * @param string $value the value to be cached. Other types (If you have disabled [[serializer]]) unable to get is 
  7.  * correct in [[getValue()]]. 
  8.  * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire. 
  9.  * @return bool true if the value is successfully stored into cache, false otherwise 
  10.  */ 
  11. protected function setValue($key$value$duration
  12.     $this->gc(); 
  13.     $cacheFile = $this->getCacheFile($key); 
  14.     if ($this->directoryLevel > 0) { 
  15.         @FileHelper::createDirectory(dirname($cacheFile), $this->dirMode, true); 
  16.     } 
  17.     // If ownership differs the touch call will fail, so we try to 
  18.     // rebuild the file from scratch by deleting it first 
  19.     // https://github.com/yiisoft/yii2/pull/16120 
  20.     if (is_file($cacheFile) && function_exists('posix_geteuid') && fileowner($cacheFile) !== posix_geteuid()) { 
  21.         @unlink($cacheFile); 
  22.     } 
  23.     if (@file_put_contents($cacheFile$value, LOCK_EX) !== false) { 
  24.         if ($this->fileMode !== null) { 
  25.             @chmod($cacheFile$this->fileMode); 
  26.         } 
  27.         if ($duration <= 0) { 
  28.             $duration = 31536000; // 1 year 
  29.         } 
  30.  
  31.         return @touch($cacheFile$duration + time()); 
  32.     } 
  33.  
  34.     $error = error_get_last(); 
  35.     Yii::warning("Unable to write cache file '{$cacheFile}': {$error['message']}"__METHOD__); 
  36.     return false; 

在设置缓存之前会主动调用清理缓存的方法gc()

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

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

这不就跟没有一样!

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

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

优化缓存配置

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

  1. 'components' => ['cache' => [ 
  2.     'class' => 'yii\caching\FileCache'
  3. ],], 

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

根据源码 public $cachePath = '@runtime/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的缓存组件,对于一般的使用者来讲,已经涵盖了超过九成的坑。

Tags: Yii2缓存 Cache

分享到: