yii中缓存(cache)详解

来源:互联网 发布:大数据建设开展情况 编辑:程序博客网 时间:2024/06/05 17:47

缓存是用于提升网站性能的一种即简单又有效的途径。通过存储相对静态的数据至缓存以备所需,我们可以省去生成这些数据的时间。在 Yii 中使用缓存主要包括配置和访问缓存组件 。

内部方法
一、缓存配置

1、单一缓存组件配置

Yii缓存可以在不同的级别使用。在最低级别,可用来缓存单个数据(数据缓存)。往上一级,我们缓存一个由视图脚本生成的页面片断(片段缓存)。在最高级别,可存储整个页面以便需要的时候直接从缓存读取。本文说明页面缓存的配置及实现效果;
实现分为2步;

1. 在config文件加入缓存组件.

'cache' => array (    'class' => 'system.caching.CFileCache',    'directoryLevel' => 2,),

class标识需要使用的缓存媒介,用途比较广的类型基本都有支持:

CMemCache: 使用 PHP memcache 扩展.

CApcCache: 使用 PHP APC 扩展.

CDbCache: 使用一张数据库表来存储缓存数据。

CFileCache: 使用文件来存储缓存数据。 特别适用于大块数据(例如页面)。

当然,yii也可以支持Redis,需要装一个插件:

http://www.yiibase.com/download/view/32.html

本文实例使用的是文件缓存,对于文件缓存,缓存到的位置为protected/runtime/;directoryLevel设置缓存文件的目录深度;如果缓存页面特别多,这个值需要设置大点,否则每个目录下的页面会很多;对于除class其他的选项的配置,可以查看各class类中的一些属性。

2. 在要做缓存的控制器里定义过滤器。

public function filters() {    return array (        array (            'COutputCache + post, list',            'duration' => 3600,            'varyByParam' => array('id','page'),            'dependency' => array(                'class'=>'CDbCacheDependency',                'sql'=>'SELECT MAX(id) FROM me115_book',                )            );    }

COutputCache 是用于处理缓存的类,如果只填’COutputCache’,则控制器里所有action都会通过缓存过滤,定义’COutputCache + post, list’,表示只对以下方法进行缓存:actionPost, actionList.
duration 是缓存的时间,单位是秒,
varyByParam 是指定一系列GET参数名称列表, 使用相应的值去确定缓存内容的版本,即同一个action用于区分是不同页面的的参数,此处我以id和page来区分不同页面。除varyByParam以外,还可以采用其他的条件来区分页面;
varyByExpression 指定缓存内容通过自定义的PHP表达式的结果而变化;
varyByRoute 指定缓存内容基于请求的路由不同而变化 (controller 和 action);
varyBySession 指定是否缓存内容. 因用户session不同而变化;
dependency 指定缓存失效依赖关系:可指定文件或数据库;本文采用的是数据库依赖CDbCacheDependency;

本例指定的是数据库,通过数据表的某个值的变化来确定缓存是否失效。例如,如果在表中新增了一条me115_book记录,即使缓存才过了2分钟(<3600),仍然判断为失效,从而查询数据库,生成整个页面,再次缓存;

检查:

查看当前页面是否缓存,可以dump输出一个当前服务器时间,从而检查当前页面是否已缓存;

优化效果:

优化站点为一个博客站点(me115.com),除了DNS解析转接外,未进行任何优化,优化前的数据为:

微考教程网-PHP开源框架Yii 缓存配置实例

微考教程网-PHP开源框架Yii 缓存配置实例

首字节时间为842ms;

采用页面缓存之后的效果:

微考教程网-PHP开源框架Yii 缓存配置实例

微考教程网-PHP开源框架Yii 缓存配置实例

首字节时间为376ms;html生成的时间大大缩短,后台时间减少了一倍。

当然,通过本图可以看到整个站点的用时还是比较长,主要是在页面组件(css/js/图片)上的下载耗费了不少时间,后续将针对这方面进行前端优化;

2、多缓存组件配置:

详看:http://hudeyong926.iteye.com/blog/1313713

//不管是多缓存配置还是单缓存配置,都需要设置一个默认的cache组件,因为CDbConnection中的schemaCacheID,queryCacheID,CCacheHttpSession 中的cacheID ,CUrlManager 中的cacheID, CStatePersister 中的cacheID都是默认的 ’cache’

‘cache’ => array(

        'class' => 'CFileCache',    ), 

‘ApcCache’=>array(

    'class'=>'CApcCache',    ),    'Dbcache'=>array(      'class'=>'CDbCache',  ),  'FileCache'=>array(      'class'=>'CFileCache',      'cachePath'=> '/Webroot/trackstar/protected/runtime/cache/test',   ),   'MemCache'=>array(      'class'=>'CMemCache',      'servers'=>array(          array(              'host'=>'server1',              'port'=>11211,              'weight'=>60,          ),          array(              'host'=>'server2',              'port'=>11211,              'weight'=>40,          ),      ),  ),   

session cache在开启apc cache时可以用,它将seesion存到apc中比存到文件中要快
‘cache’ => array(
‘class’ => ‘CApcCache’,
),
‘session’ => array(
‘class’ => ‘CCacheHttpSession’, //CCacheHttpSession在system.web包里
),

yii如果要使用session.save_handler=memcache 如果需要扩展自定义的session管理方法 ,仅仅需要继承CHttpSession, 重写openSession,readSession,writeSession, destroySession,gcSession 这五个方法即可

3、数据库缓存配置:
//main.php配置文件中 数据库缓存配置,具体参照CDbConnection
‘schemaCachingDuration’ => 3600, //缓存时间
‘schemaCachingExclude’ => array(), //不需要缓存的表名数组
‘schemaCacheID’ => ‘cache’, //使用的缓存组件

此外,CDbConnection中还有关于数据库查询的缓存配置,不过这里只是一个全局的配置
//查询缓存配置
‘queryCachingDuration’ => 3600,//缓存时间
‘queryCachingDependency’ => null, //缓存依赖
‘queryCachingCount’ => 2, //第一次使用这条sql语句后同样的多少条sql语句需要缓存
‘queryCacheID’ => ‘cache’, //使用的缓存组件

需要配置数据库查询缓存,可以使用使用以下方法:

一、CDbConnection中的cache方法
public CDbConnection cache(integer duration,CCacheDependencydependency=NULL, integer queryCount=1)duration integer 查询结果保持在缓存中有效的秒数。如果它是0,缓存将被禁用。
dependencyCCacheDependency使queryCount integer 在调用此方法后,需要缓存的SQL查询的数目。默认为 1,意味着下一条SQL查询将被缓存。
{return} CDbConnection 返回连接实例本身。
public function cache(duration,dependency=null, queryCount=1)  
{
this->queryCachingDuration=duration;this->queryCachingDependency=dependency;this->queryCachingCount=queryCount;returnthis;
}

例子:
sql=SELECTFROMtblpostLIMIT20;dependency = new CDbCacheDependency(‘SELECT MAX(update_time) FROM tbl_post’);
rows=Yii::app()>db>cache(1000,dependency)->createCommand($sql)->queryAll();

二、CActiveRecord中的cache方法:
public CActiveRecord cache(integer duration,CCacheDependencydependency=NULL, integer queryCount=1)duration integer 查询结果可能保持在缓存中有效的秒数。如果这是0,缓存将被禁用。
dependencyCCacheDependency使queryCount integer 在调用此方法后,需要缓存的SQL查询的数目。 默认值为 1,这意味着下一个SQL查询将被缓存。
{return} CActiveRecord AR实例本身。
public function cache(duration,dependency=null, queryCount=1)  
{  
    //实际上他调用的是CDbConnection中的cache方法
this->getDbConnection()->cache(duration,dependency, queryCount);returnthis;
}

例子:
dependency=newCDbCacheDependency(SELECTMAX(updatetime)FROMtblpost);posts = Post::model()->cache(1000, $dependency)->findAll();

关于$queryCount:
启用查询缓存

要使用查询缓存,首先要确保CDbConnection::queryCacheID指向一个可用的缓存组件ID(默认是cache)。

用DAO查询缓存

要使用查询缓存,我们在数据库查询的时候调用CDbConnection::cache()这个方法。例如:

sql=SELECTFROMtblpostLIMIT20;dependency = new CDbCacheDependency(‘SELECT MAX(update_time) FROM tbl_post’);
rows=Yii::app()>db>cache(1000,dependency)->createCommand($sql)->queryAll();
执行以上语句的时候,Yii会首先检查一下缓存是否包含一个该语句的查询结果。检查步骤是以下的三个条件:

●如果缓存包含了SQL语句中的入口索引
●如果入口还没过期(少于保存后的1000秒)
●如果依赖关系没有变化(update_time的最大值是跟查询结果保存到缓存时一致)

如果以上3个条件都满足了,缓存的结果就会直接返回给请求。否则,SQL语句就会被传递到数据库系统去执行,得到的结果会保存到缓存,返回给请求。

用AR查询缓存

我们也可以用AR来查询缓存。我们用一个类似的方法,调用CActiveRecord::cache():

dependency=newCDbCacheDependency(SELECTMAX(updatetime)FROMtblpost);posts = Post::model()->cache(1000, dependency)>findAll();//relationalARqueryposts = Post::model()->cache(1000, $dependency)->with(‘author’)->findAll();
上面的cache()方法,实际上是CDbConnection::cache()的快捷方式。在内部,当执行AR的查询语句是,Yii会尝试我们之前讲述过的查询缓存。

缓存的多种查询

默认情况下,我们每次调用cache()(不管是CDbConnection 还是 CActiveRecord),都会标记下次要缓存的SQL,其他任何的SQL查询都不会被缓存,除非我们再次调用cache(),例如:

sql=SELECTFROMtblpostLIMIT20;dependency = new CDbCacheDependency(‘SELECT MAX(update_time) FROM tbl post’);
rows=Yii::app()>db>cache(1000,dependency)->createCommand(sql)>queryAll();//querycachingwillNOTbeusedrows = Yii::app()->db->createCommand(sql)>queryAll();queryCount到cache()的方法中,我们可以强制多次查询缓存。下面的例子中,通过调用call(),我们指定这个换成必须用于接下来的2次

// …
rows=Yii::app()>db>cache(1000,dependency, 2)->createCommand(sql)>queryAll();//querycachingWILLbeusedrows = Yii::app()->db->createCommand($sql)->queryAll();
如你所知,当我们执行关联AR查询时,可能是执行多句的SQL。例如,Post与Coment之间的关系是HAS_MANY,以下的SQL语句是数据库中真正执行的。

it first selects the posts limited by 20;
it then selects the comments for the previously selected posts.

$posts = Post::model()->with(‘comments’)->findAll(array(
‘limit’=>20,
));
如果我们用下面的语句查询缓存,只有第一句会被缓存:

posts=Post::model()>cache(1000,dependency)->with(‘comments’)->findAll(array(
‘limit’=>20,
));
如果要缓存两个,我们要提供额外的参数来指明接下来我们要缓存几句:

posts=Post::model()>cache(1000,dependency, 2)->with(‘comments’)->findAll(array(
‘limit’=>20,
));
限制

如果查询结果中包含资源句柄,查询访问就不能用了。例如,我们在某些数据库系统中使用BLOB作为字段类型,查询结果会返回一个资源句柄给这个字段。

有些缓存器会有大小限制。例如mencache限制每个入口大小为1M,所以,当一个查询结果大于该大小时,会缓存失败。

二、缓存的运用

提示 : 因为所有这些缓存组件都从同一个基础类 CCache 扩展而来,不需要修改使用缓存的代码即可在不同的缓存组
件之间切换。

缓存可以在不同的级别使用。在最低级别,我们使用缓存来存储单个数据,比如一个变量,我们把它叫做 数据缓存 。
往上一级,我们缓存一个由视图脚本生成的页面片断。在最高级别,我们存储整个页面以便需要的时候直接从缓存读
取。
接下来我们将阐述如何在这些级别上使用缓存。
注意 : 按定义来讲 , 缓存是一个不稳定的存储媒介 , 它不保证缓存一定存在 —— 不管该缓存是否过期 。 所以 , 不要使用
缓存进行持久存储(比如,不要使用缓存来存储 SESSION 数据 ) 。

一、数据缓存

数据缓存也就是在缓存中存储一些 PHP 变量 , 过一会再取出来 。 缓存基础类 CCache 提供了两个最常用的方法 : set()
和 get() 。
要在缓存中存储变量 valueIDset()Yii::app()>cache>set(id, value);set()//30Yii::app()>cache>set(id, $value, 30);
当我们稍后需要访问该变量时 ( 不管是不是同一 Web 请求 ) , 我们调用 get() ( 传入 ID ) 来从缓存中获取它 。 如果返
回值为 false ,说明该缓存不可用,需要我们重新生成它。

value=Yii::app()>cache>get(id);
if(value===false)  
{  
// 因为在缓存中没找到,重新生成
value
// 再缓存一下以备下次使用
// Yii::app()->cache->set(id,value);
}
为一个要缓存的变量选择 ID 时,确保该 ID 在应用中是唯一的。不必保证 ID 在跨应用的情况下保证唯一,因为缓
存组件有足够的智能来区分不同应用的缓存 ID 。
要从缓存中删除一个缓存值 , 调用 delete() ; 要清空所有缓存 , 调用 flush() 。 调用 flush() 时要非常小心 , 因为它会把
其它应用的缓存也清空。
提示 : 因为 CCache 实现了 ArrayAccess 接口,可以像数组一样使用缓存组件。例如:

cache=Yii::app()>cache;cache['var1']=value1;//:cache->set('var1',value1);value2=cache[var2];//:value2=cache>get(var2);CCacheDependencyset()//30//Yii::app()>cache>set(id, value,30,newCFileCacheDependency(FileName));get()value ,缓存组件将检查依赖条件。如果有变,我们会得到 false 值 —— 数据
需要重新生成。
下面是可用的缓存依赖的简要说明:
CFileCacheDependency: 该依赖因文件的最近修改时间发生改变而改变。
CDirectoryCacheDependency: 该依赖因目录(或其子目录)下的任何文件发生改变而改变。
CDbCacheDependency: 该依赖因指定的 SQL 语句的查询结果发生改变而改变。
CGlobalStateCacheDependency: 该依赖因指定的全局状态值发生改变而改变。全局状态是应用中跨请求、跨 SESSION
的持久变量,它由 CApplication::setGlobalState() 来定义。
CChainedCacheDependency: 该依赖因依赖链中的任何一环发生改变而改变。

二、片段缓存 (Fragment Caching)

片段缓存指缓存网页某片段。例如,如果一个页面在表中显示每年的销售摘要,我们可以存储此表在缓存中,减少每
次请求需要重新产生的时间。
要使用片段缓存,在控制器视图脚本中调用 CController::beginCache() 和 CController::endCache() 。这两种方法开始和
结束包括的页面内容将被缓存。类似 data caching ,我们需要一个编号,识别被缓存的片段。
… 别的 HTML 内容 …

1 0
原创粉丝点击