有的兄弟必定会说,File缓存有什么好讲的那?不就是一个set,而后在一个get么?那你知道的只是皮毛~php
的确如你们所说,缓存从表现层看就是一个set(放数据),而后再一个get(拿数据),可是请记住,这样是不够的,若是你不了解每一个缓存的实现原理、存储特色等等,你是没法使用对场景的,何时用File缓存、何时用DB缓存、何时用Memcache缓存,这些才是咱们要学的。html
依然先写目录web
FileCache的定义sql
FileCache的基本用法数据库
FileCache存储内容时的逻辑实现json
可能一句话就能够说明白,将某些数据存到文件中,下次读取的时候直接从文件中读,分流压力。数组
为了统一接口,yii2将全部类型的缓存都统一成如下这些方法。缓存
get() // 根据一个指定的key获取缓存值,若是缓存不存在或已通过期则返回false set() // 直接保存一个值到缓存(不考虑是否存在,直接替换) add() // 若是此刻缓存不存在则保存,不然忽略 multiGet() // 一次获取多个key的缓存值,参数为一个key的数组["key1","key2"],返回值也是一个数组["key1"=>"valuw1","key2"=>"value2"] multiSet() // 一次存储多个缓存 mulitAdd() // 一次添加多个缓存 delete() // 删除某个缓存 flush() // 删除全部缓存
以上8个方法我想经过文档你们均可以看明白,着实没什么难度,还有两个方法在这里重点说下,它们理解起来稍微蹩脚一些。yii2
exists() getOrSet()
exists($key)
顾名思义,检查一个缓存是否存在(缓存过时 = 过时)。对于这个函数要注意如下几点数据结构
当缓存的数据量很大时,使用exists要比get快,可是若是缓存没有原生的exists,则exists会去模拟一下,这种状况下exists不会比get有性能提升,FileCache 的exists未有提高。
exists并不会检查缓存依赖,因此若是一个缓存有依赖而依赖的变化致使咱们经过get获取的值是false,可是有可能exists获取的是true,这点要注意下。
getOrSet($key, Closure $closure, $duration = null, $dependency = null)
这是v2.0.11增长的一个新的方法。
$data = $cache->getOrSet($key, function () { return $this->calculateSomething(); });
等同于
$data = $cache->get($key); if ($data === false) { $data = $this->calculateSomething(); $cache->set($key, $data); }
这个函数的用意是简单的-若是有则获取,没有则创建,可是其中的$closure要提一下,它接收一个闭包。闭包是php5.3引入的一个新概念,若是不知道的能够用下面网址补课一下
http://www.cnblogs.com/melonb...
因而咱们就能够写一个你可能不常见的缓存代码
$cache->getOrSet(['user','id'=>$id],function($cache) use ($id){ return User::findOne($id); });
缓存每个会员的信息,使用use,最少代码量。
以上就是yii2 Cache对支持的全部缓存统一的10个方法,下面咱们会针对FileCache进行一些原理性说明,为了方便你们阅读,咱们用问答模式。
上帝问: 北哥,看文档我看什么get、set、getOrSet的key除了一个字符串,还能接收一个数据结构,是什么意思?
北哥答:是的,你说的不错,好比咱们如今要缓存每一个文章,咱们可使用如下两个方法
// key是string的 $cache->set("article-1",$data); // key是结构体,好比数组 $cache->set(["article","id"=>1],$data);
这两种形式均可以,我想你必定会问这些key是如何识别的那,在runtime的 cache我如何找到他们那?
上帝问: 是的北哥,您说的对,好比个人key=abc,那么存储的时候是如何根据key来创建文件夹或缓存文件的那,他们是如何命名的那?
北哥答: yii对于文件缓存key的处理以下,我用伪代码回答你。
// 对用户缓存定义的key进行再加工 if($key == 字符串){ if($key字符串只含有数字或字母 && $key的长度 <= 32 ){ return $key; }else{ md5($key) } }else{ return md5(json_encode($key)); // 数字的key、数组的key都被md5了。 }
所以你能看到可能让你蒙圈的缓存文件,以下图
如今不蒙圈了吧。可是必定要注意,看下面代码
$cache->set("123",$data); $cache->set(123,$data);
语句1会生成一个123.bin的缓存文件,由于"123"是字符串,而语句2的123是数字,会生成md5(123)后的.bin文件。
如今你明白了文件命名规则,我想上帝你必定也被那些1三、5九、a三、le这样的文件夹弄晕了吧,再仔细看一下,是的,你发现了。。。
是文件名的前两个字母
恭喜你,这是一个多么准确且伟大的发现。可是,我想你也必定见过这样的缓存目录
目录不止一级,不少级,这样是有道理的,能够保证一个文件夹内文件不会过多,可是这个是如何实现的那?
这仅仅是一个变量决定,它叫directoryLevel(默认为1)
$cache->directoryLevel = 3;
固然你也能够在web的cache里配置,仍是按照你刚才发现的密码,若是directoryLevel=3,则把文件名从头开始,每2字符个作一个文件夹(若是文件名只有3个字符,则创建到第二个的时候中止就行了)。
好的上帝,如今你明白了吧~
上帝问: 你说的我明白了,我还有个问题,好比我在我模块里set了一个key=abc的缓存,别人也set了一个key=abc的缓存(和个人key不是一个含义),那岂不是被覆盖了,能不能避免?
北哥答: 必须的了,你可使用一个叫作keyPrefix的变量,它为你的缓存文件名字加一个前缀,看代码
$cache->keyPrefix = "nai8_"; $cache->set("hello","hello keyPrefix");
结果以下
这回你不怕了,看看谁还敢和你冲突。
上帝问: 我基本都明白了,再问你一个问题,回答完后我就回花果山了,就是好比我写了$cache->set("a","abc",1000),可是当我get的时候,yii怎么知道到了1000秒,已通过期仍是没过时那,我看文件内容里没有1000这个数字啊,到底存在什么地方?
北哥答: 你说的没错,这要介绍一个php的函数了 --- touch(),这个函数能够修改一个文件的上一次修改时间,当咱们执行 $cache->set("a","abc",1000)时候,yii的FileCache作了一件事情,看代码
touch("缓存文件",(time() + 1000));
你明白了吧,当咱们读的时候,只须要判断filetime("缓存文件")的上次修改时间是否大于如今time(),不就能够了么,多简单的事情。
OMG~ Fly fly fly ......
但是我还没说完~
下面开始北哥自言自语一小段,讲讲缓存依赖(set、add、getOrSet都有这个参数),什么意思那,简单的说就是一个缓存和某个东东有关联,当这个东东发生变化时,则这个缓存失效(既是当前过时时间还没到)
由于篇幅问题,咱们这里先说一个Cache的数据库依赖,之后会在“北哥大话Yii2缓存机制”单独拿出一篇来说各类依赖。
$dependency = new \yii\caching\DbDependency( ['sql' => 'SELECT count(*) FROM user'] ); // 当数据库字段发生变化时,该缓存失效 $cache->add('three', 'hello world!', 3000, $dependency);
依赖仍是蛮有用的,好比一些统计数据的显示作缓存,当数据变化时缓存数据能获得及时的更新。
讲的好长~做为“北哥大话Yii2缓存机制”第一篇,但愿你们喜欢,为了一段日子里我会专一于分享yii2的缓存机制。
感谢兄弟连各位兄弟的大力支持。