第二层内功 - 数据缓存

  • 作者: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:

  1. yii\caching\FileCache 使用标准文件存储缓存数据。 这个特别适用于缓存大块数据,例如一个整页的内容。

  2. yii\caching\ApcCache 使用 PHP APC 扩展。 这个选项可以认为是集中式应用程序环境中 (例如:单一服务器,没有独立的负载均衡器等)最快的缓存方案。

  3. yii\caching\DbCache 使用一个数据库的表存储缓存数据。要使用这个缓存, 你必须创建一个与 yii\caching\DbCache::$cacheTable 对应的表。

  4. yii\caching\MemCache 使用 PHP memcache 和 memcached 扩展。 这个选项被看作分布式应用环境中(例如:多台服务器,有负载均衡等) 最快的缓存方案。

  5. yii\redis\Cache 实现了一个基于 Redis 键值对存储器的缓存组件 (需要 redis 2.6.12 及以上版本的支持 )。

  6. yii\caching\WinCache 使用 PHP WinCache (另可参考)扩展.

  7. yii\caching\XCache 使用 PHP XCache扩展。

  8. 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语句的查询结果发生变化时就会让缓存失效


其它缓存依赖

以下是更加少用的缓存依赖,可以在官方文档里找到介绍


查询缓存

可以通过很简单的代码就能让查询的数据自动缓存起来,下次查询就先找缓存:

$缓存时长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组件主要有两个主要属性可以控制缓存

  1. enableQueryCache,boolean值,控制是否允许使用缓存,默认为true,如果设置为false,那上面的db->cache都不会第一次,永远都会跑数据库,想统一关闭所有查询缓存时就改这个属性好了,代码不需要修改

  2. queryCacheDuration,秒数,也是指上面查询缓存的过期时间,默认为0(不过期)

另外还有一个queryCache的配置默认值是“cache”,它是指缓存时使用哪个组件名称,如果你配置为cache2那底层就会使用Yii::$app->cache2这个组件来存取缓存


清空缓存

Yii::$app->cache->flush()