Yii2数据缓存详解

数据缓存是指将一些 PHP 变量存储到缓存中,使用时再从缓存中取回。 它也是更高级缓存特性的基础,例如查询缓存 和内容缓存。

缓存组件

数据缓存需要缓存组件提供支持,它代表各种缓存存储器, 例如内存,文件,数据库。

'components' => [
    'cache' => [
              'class' => 'yii\caching\FileCache',
              // 上面这种是Yii默认的缓存方式,标准文件缓存数据,当然也可以使用其他方式,如:
              // 'class' => 'yii\caching\MemCache',
              // 'class' => 'yii\caching\ApcCache',
          ],
]

 

支持的缓存方式
  • yii\caching\ApcCache:使用 PHP APC 扩展。这个选项可以 认为是集中式应用程序环境中(例如:单一服务器, 没有独立的负载均衡器等)最快的缓存方案。
  • yii\caching\DbCache:使用一个数据库的表存储缓存数据。要使用这个缓存,你必须 创建一个与 yii\caching\DbCache::cacheTable 对应的表。
  • yii\caching\DummyCache:仅作为一个缓存占位符,不实现任何真正的缓存功能。 这个组件的目的是为了简化那些需要查询缓存有效性的代码。 例如,在开发中如果服务器没有实际的缓存支持,用它配置 一个缓存组件。一个真正的缓存服务启用后,可以再切换为使用相应的缓存组件。 两种条件下你都可以使用同样的代码 Yii::$app->cache->get($key) 尝试从缓存中取回数据而不用担心 Yii::$app->cache 可能是 null
  • yii\caching\FileCache:使用标准文件存储缓存数据。这个特别适用于 缓存大块数据,例如一个整页的内容。
  • yii\caching\MemCache:使用 PHP memcachememcached 扩展。 这个选项被看作分布式应用环境中(例如:多台服务器, 有负载均衡等)最快的缓存方案。
  • yii\redis\Cache:实现了一个基于 Redis 键值对存储器 的缓存组件(需要 redis 2.6.12 及以上版本的支持 )。
  • yii\caching\WinCache:使用 PHP WinCache (另可参考 )扩展。
  • yii\caching\XCache:使用 PHP XCache扩展。
  • yii\caching\ZendDataCache:使用 Zend Data Cache 作为底层缓存媒介。

缓存的增删改查示例

// 加载缓存组件
$cache = \Yii::$app->cache;

// 添加一个缓存
$cache->add('name','zhangsan');

// 更改一个缓存
$cache->set('name' , 'lisi');

// 删除一个缓存
$cache->delete('name');

// 获取缓存内容
$cache->get('name')

// 查看缓存是否存在
if($cache->exists('name')){
    echo '存在';
}

// 同时增加多个缓存
$cache->madd(['name' => 'zhangsan' , 'age' => 18]);

// 同时获取多个缓存
var_dump($cache->mget(['name'  , 'age']));

// 清空缓存
$cache->flush();

设置缓存有效期

默认情况下,缓存中的数据会永久存留,除非它被某些缓存策略强制移除(例如: 缓存空间已满,最老的数据会被移除)。要想改变此特性,可以使用 yii\caching\Cache::add()yii\caching\Cache::set() 的第三个参数来改变。

// 加载缓存组件
$cache = \Yii::$app->cache;
// 默认该缓存在20秒之后过期
$cache->add('name','zhangsan',20);
// 同样
$cache->set('name','zhangsan',20);

缓存依赖

除了超时设置,缓存数据还可能受到缓存依赖的影响而失效。我们可以使用 yii\caching\Cache::add()yii\caching\Cache::set() 的第四个参数来设置。

// 加载组件
$cache = \Yii::$app->cache;

// 文件依赖
$dependency = new \yii\caching\FileDependency(['fileName'=>'robots.txt']);
// 如果 robots.txt 被修改,该缓存也立刻失效
$cache->add('the', 'hello world!', 3000, $dependency);
$result = $cache->get('the');

// 表达式依赖
$dependency = new \yii\caching\ExpressionDependency(
    ['expression' => '\Yii::$app->request->get("name")']
);
// 这里使用的表达式是获取$_GET['name']的值,如果值改变,该缓存失效
$cache->add('two', 'hello world!', 3000, $dependency);
$result = $cache->get('two');

// 数据库依赖
$dependency = new \yii\caching\DbDependency(
    ['sql' => 'SELECT count(*) FROM test.user']
);
// 当数据库字段发生变化时,该缓存失效
$cache->add('three', 'hello world!', 3000, $dependency);
$result = $cache->get('three');

 

举个列子:
在一个数据比较庞大的订单记录中统计时间段内的成交金额,以及利润,在这样的查询页面会产生过多的加载时间,等待是痛苦的。我们可以将查询的结果按时间段存储到缓存中,订单是变化的,统计的时间段一旦涉及今天,则统计需依赖订单的最新创建时间,如创建时间变化,此时缓存失效,可重新生成缓存;反之,缓存不受影响;

/*订单表(order) id uerid price type(订单类型) state(1为已支付 0 未支付) paytime  createtime isdelete*/ 

#查询成交金额 

function ordercheck($starttime,$endtime){   

    $cacheid = "order".$starttime.$endtime;   //设置缓存id     

    if( !Yii::app()->cache->get($cacheid) ){       

        $sql = "SELECT SUM(price)  as sumprice FROM order WHERE  state=1 AND isdelete=0";        

        $addsql = '';          

        if( $starttime ) $addsql.=" AND createtime>={$starttime}";       

        if( $endtime ) $addsql.=" AND createtime>={$endtime}";       

        $res = Yii::app()->createCommand($sql.$addsql)->queryAll;        //开始时间或结束时间大于等于今天时间戳则建立依赖       

        $date = date('Y-m-d',time());        

        if( $starttime>=strtotime($date) || $endtime>=strtotime($date) ){             

          //依赖条件为最新的订单时间发生改变   

          $dependency = new CDbCacheDependency('SELECT MAX(createtime)  FROM order WHERE  state=1 AND isdelete=0');          

            Yii::app()->cache->set($cacheid,$res['sumprice'] , 1800,$dependency);        

        }else{    

            Yii::app()->cache->set($cacheid, $res['sumprice'], 1800);       

        }   

    }    

    return Yii::app()->cache->get($cacheid) ;    

} 

  

posted @ 2018-10-08 18:28  llxpbbs  阅读(2942)  评论(0编辑  收藏  举报