有的兄弟必定會說,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的緩存機制。
感謝兄弟連各位兄弟的大力支持。