第二层内功 - 数据缓存 ¶
作者:KK
发表日期:2017.9.19
介绍和配置 ¶
Yii的应用模板默认配置了一个叫cache
的缓存组件,而且这个组件被框架的各个类引用(默认的,一般都可以修改),就是说如果你不配置cache组件,那其它类(比如数据库查询)无法使用缓存,除非你很会玩,自己搞个cache2然后修改了数据库的组件的一些配置就可以对应起来
虽然cache不是一个核心组件,但也是经常会用到的组件,主要配置如下:
'components' => [
'cache' => [
'class' => 'yii\caching\FileCache',
],
]
上面通过将缓存组件的类设置为yii\caching\FileCache,就配置好了缓存组件,这是一个文件缓存组件
快速示例 ¶
Yii::$app->cache->set('count', 99);
$count = Yii::$app->cache->get('count');
echo $count; // 99
支持的缓存类型 ¶
这是通过文件来存放缓存数据,而yii支持以下缓存媒介,使用方法也是get和set:
yii\caching\FileCache 使用标准文件存储缓存数据。 这个特别适用于缓存大块数据,例如一个整页的内容。
yii\caching\ApcCache 使用 PHP APC 扩展。 这个选项可以认为是集中式应用程序环境中 (例如:单一服务器,没有独立的负载均衡器等)最快的缓存方案。
yii\caching\DbCache 使用一个数据库的表存储缓存数据。要使用这个缓存, 你必须创建一个与 yii\caching\DbCache::$cacheTable 对应的表。
yii\caching\MemCache 使用 PHP memcache 和 memcached 扩展。 这个选项被看作分布式应用环境中(例如:多台服务器,有负载均衡等) 最快的缓存方案。
yii\redis\Cache 实现了一个基于 Redis 键值对存储器的缓存组件 (需要 redis 2.6.12 及以上版本的支持 )。
yii\caching\WinCache 使用 PHP WinCache (另可参考)扩展.
yii\caching\XCache 使用 PHP XCache扩展。
yii\caching\ZendDataCache 使用 Zend Data Cache 作为底层缓存媒介。
有些缓存要配置缓存服务器地址、端口以及密码的,请注意看相关的详细介绍,这里只是快速介绍缓存组件
缓存过期控制 ¶
set的第3个参数用于控制过期时间
Yii::$app->cache->set('aa', 11, 5); // 5秒后过期
echo Yii::$app->cache->get('aa'); // 5秒后再get就是空,5秒内你还能取到值
除了get和set以外的API ¶
上面所有缓存组件都继承了yii\caching\Cache,所以它们都有统一的缓存操作方法,如下(引用官方的解释):
- get():通过一个指定的键(key)从缓存中取回一项数据。 如果该项数据不存在于缓存中或者已经过期/失效,则返回值 false。
- set():将一个由键指定的数据项存放到缓存中。
- add():如果缓存中未找到该键,则将指定数据存放到缓存中。
- getOrSet():返回由键指定的缓存项,或者执行回调函数,把函数的返回值用键来关联存储到缓存中,最后返回这个函数的返回值。
- multiGet():由指定的键获取多个缓存数据项。
- multiSet():一次存储多个数据项到缓存中,每个数据都由一个键来指明。
- multiAdd():一次存储多个数据项到缓存中,每个数据都由一个键来指明。如果某个键已经存在,则略过该数据项不缓存。
- exists():返回一个值,指明某个键是否存在于缓存中。
- delete():通过一个键,删除缓存中对应的值。
- flush():删除缓存中的所有数据。
注意: 千万别直接用
false
布尔值当做数据项缓存,因为get()方法用false
作为返回值来表名对应的缓存项不存在。你可以把false
放到一个数组里然后缓存这个数组来避免上述的混淆问题。
有些缓存存储器如 MemCache,APC 支持以批量模式取回缓存值,这样可以节省取回缓存数据的开支。 multiGet() 和 multiAdd() API提供对该特性的支持。 如果底层缓存存储器不支持该特性,Yii 也会模拟实现。
缓存依赖 ¶
有时候我们需要检测一些其它东西来判断是否使用缓存,就可以用上这个缓存依赖,比如说一个文件的修改时间如果变化了,那缓存就失效,要重新生成缓存
// 创建一个对 example.txt 文件修改时间的缓存依赖
$dependency = new \yii\caching\FileDependency(['fileName' => 'example.txt']);
// 缓存数据将在30秒后超时
// 如果 example.txt 被修改,它也可能被更早地置为失效状态。
$cache->set($key, $data, 30, $dependency);
// 缓存会检查数据是否已超时。
// 它还会检查关联的依赖是否已变化。
// 符合任何一个条件时都会返回 false。
$data = $cache->get($key);
数据库缓存依赖 ¶
$sql = (new \yii\db\Query())->from('user')->where(['type' => 3])->createCommand()->rawSql;
$dependency = new \yii\caching\DbDependency(['sql' => $sql]);
$cache->set($key, $data, 30, $dependency);
$data = $cache->get($key);
当以上SQL语句的查询结果发生变化时就会让缓存失效
其它缓存依赖 ¶
以下是更加少用的缓存依赖,可以在官方文档里找到介绍
- yii\caching\ChainedDependency:如果依赖链上任何一个依赖产生变化,则依赖改变。
- yii\caching\ExpressionDependency:如果指定的 PHP 表达式执行结果发生变化,则依赖改变。
- yii\caching\TagDependency: 这个我暂时也不是很懂,大家研究研究一起回复探讨哈
查询缓存 ¶
可以通过很简单的代码就能让查询的数据自动缓存起来,下次查询就先找缓存:
$缓存时长60; //秒
$count = Yii::$app->db->cache(function($db){
return Article::find()->where($condition)->count();
}, $缓存时长
cache
方法接受三个参数,分别是执行函数、缓存时长、缓存依赖
在AR层也可以使用:
$count = Article::getDb()->cache(function($db){
return Article::find()->where($condition)->count();
});
其实本质上getDb也是取得了一个db组件,如果项目里没有定义两个db组件那是没有区别的,是指同一个对象
db组件主要有两个主要属性可以控制缓存
enableQueryCache
,boolean值,控制是否允许使用缓存,默认为true,如果设置为false,那上面的db->cache都不会第一次,永远都会跑数据库,想统一关闭所有查询缓存时就改这个属性好了,代码不需要修改queryCacheDuration
,秒数,也是指上面查询缓存的过期时间,默认为0(不过期)
另外还有一个queryCache
的配置默认值是“cache”,它是指缓存时使用哪个组件名称,如果你配置为cache2
那底层就会使用Yii::$app->cache2
这个组件来存取缓存
清空缓存 ¶
Yii::$app->cache->flush()