什么是緩存組件cache
緩存是提升 web 應用性能簡便有效的方式。 通過將相對靜態的數據存儲到緩存并在收到請求時取回緩存, 應用程序便節省了每次重新生成這些數據所需的時間。
定義緩存組件
yii2的緩存是通過組件component實現的,在項目的配置文件中,配置components->cache實現對緩存組件的定義。
項目配置文件的路徑為config/web.php。
頁面緩存pagecache
作為網站來講,yii2的頁面緩存非常便捷地將已經渲染完全的網頁結果保存起來,并在一個緩存周期內不需要再次處理頁面內部的控制器動作邏輯。
配置頁面緩存
頁面緩存的配置方式為,在控制器層controller中配置行為behaviors,通過調用過濾器filters的方式,在進入具體頁面路徑action的之前,對當前key進行計算,并判斷緩存是否啟用enabled緩存有效期duration。
基礎配置代碼如下所示
1
2
3
4
5
6
7
8
9
10
11
12
|
return [ 'pagecache' => [ 'class' => 'yii\filters\pagecache' , 'only' => [ 'index' ], 'variations' => [ '/' , yii:: $app ->request->isajax, ], 'enabled' =>true, 'duration' => yii:: $app ->params[ 'pagecacheduration' ], ], ]; |
過濾器是yii2中的一個概念,他可以在控制器初始化的時候加載并執行,我們可以用這個特點去做一些對控制器的數據的限制,比如控制緩存、用戶權限控制。
這里我們將行為名稱定義為pagecache,顯然名字不重要,因為有的案例中,因為不同的頁面緩存規則不一樣,我會定義兩個頁面緩存的行為。
其中only為過濾器調用action的參數,用于限制哪些路徑是啟用action的。
頁面緩存pagecache是緩存組件cache的一種應用
頁面緩存的根本邏輯為
- 配置緩存組件的實現比如文件緩存yii\caching\filecache
- 頁面緩存封裝一層cache組件,再去調用存取邏輯
我們可以通過查看頁面緩存源碼vendor/yiisoft/yii2/filters/pagecache.php,我們可以在文件的第162行發現,這里調用的cache,就是對于緩存的實現。
1
|
$this ->cache = instance::ensure( $this ->cache, 'yii\caching\cacheinterface' ); |
自定義頁面緩存過濾器
為什么我們需要自定義緩存組件呢,我歸納原因存在以下幾種
- 緩存判斷邏輯過于簡單或復雜,不如自己重寫痛快地多
- 緩存key生成方式不滿足業務需求
那么如何自定義呢?我個人推薦最簡單粗暴的方式,繼承。
1
2
3
4
5
6
7
|
use yii\filters\pagecache; class pagecachectinfo extends pagecache { 這里是內部邏輯,不需要重寫的方法可以不寫。 public $checkuser = true; //可以自定義變量 } |
調用方式也是跟默認的頁面緩存一樣,只要換上對應的類即可。
1
2
3
4
5
6
7
8
9
10
11
|
'pagecacheinfo' => [ 'class' => 'common\components\pagecachectinfo' , 'only' => [ 'info' ], 'enabled' =>yii:: $app ->params[ 'pagecacheenabled' ], 'variations' => [ 'ct/' .yii:: $app ->request-> pathinfo , yii:: $app ->request->isajax ], 'duration' => yii:: $app ->params[ 'pagecacheinfo' ], 'checkuser' = false, ], |
頁面緩存key的計算
根據上一個步驟,我們可以重寫計算key的方式,那么之前的key計算方式是什么樣的呢?
文件位置vendor/yiisoft/yii2/filters/pagecache.php。
1
2
3
4
5
6
7
8
9
10
11
12
|
/** * @return array the key used to cache response properties. * @since 2.0.3 */ protected function calculatecachekey() { $key = [ __class__ ]; if ( $this ->varybyroute) { $key [] = yii:: $app ->requestedroute; } return array_merge ( $key , ( array ) $this ->variations); } |
這里的緩存key是一個數組,數組內的元素依次是
- 當前類名
- varybyroute 一般為true
- variations 驗證,這個也是配置中獲取的,根據上面的配置,則是頁面路徑和是否為ajax
如果是項目的首頁,緩存的key則為
1
|
[ 'yii\filters\pagecache' , '' ,'/‘,0] |
如果是個詳情頁面,key為
1
|
[ 'yii\filters\pagecach' , 'xxx/info' , 'xxx/xxx/3xxxx74.html' ,0 ] |
那么,這個key到底有什么用,為什么要單獨拿出來說呢?
因為我們需要單獨刪除某個頁面緩存。
主動清理過期緩存
根據源碼vendor/yiisoft/yii2/caching/filecache.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
/** * stores a value identified by a key in cache. * this is the implementation of the method declared in the parent class. * * @param string $key the key identifying the value to be cached * @param string $value the value to be cached. other types (if you have disabled [[serializer]]) unable to get is * correct in [[getvalue()]]. * @param int $duration the number of seconds in which the cached value will expire. 0 means never expire. * @return bool true if the value is successfully stored into cache, false otherwise */ protected function setvalue( $key , $value , $duration ) { $this ->gc(); $cachefile = $this ->getcachefile( $key ); if ( $this ->directorylevel > 0) { @filehelper::createdirectory(dirname( $cachefile ), $this ->dirmode, true); } // if ownership differs the touch call will fail, so we try to // rebuild the file from scratch by deleting it first // https://github.com/yiisoft/yii2/pull/16120 if ( is_file ( $cachefile ) && function_exists( 'posix_geteuid' ) && fileowner ( $cachefile ) !== posix_geteuid()) { @unlink( $cachefile ); } if (@ file_put_contents ( $cachefile , $value , lock_ex) !== false) { if ( $this ->filemode !== null) { @ chmod ( $cachefile , $this ->filemode); } if ( $duration <= 0) { $duration = 31536000; // 1 year } return @touch( $cachefile , $duration + time()); } $error = error_get_last(); yii::warning( "unable to write cache file '{$cachefile}': {$error['message']}" , __method__ ); return false; } |
在設置緩存之前會主動調用清理緩存的方法gc()
1
2
3
4
5
6
7
8
9
10
11
12
13
|
/** * removes expired cache files. * @param bool $force whether to enforce the garbage collection regardless of [[gcprobability]]. * defaults to false, meaning the actual deletion happens with the probability as specified by [[gcprobability]]. * @param bool $expiredonly whether to removed expired cache files only. * if false, all cache files under [[cachepath]] will be removed. */ public function gc( $force = false, $expiredonly = true) { if ( $force || mt_rand(0, 1000000) < $this ->gcprobability) { $this ->gcrecursive( $this ->cachepath, $expiredonly ); } } |
這里問題就出現了,$gcprobability的默認值是10,也就是說,只有0.001%的概率會在設置緩存的同時清理過期緩存。
這不就跟沒有一樣!
所以對于緩存來說,需要我們主動定期清理過期緩存,不然對應的存儲空間就會被占滿。
1
|
yii:: $app ->cache->gc(true); |
優化緩存配置
組件的cache在項目的配置文件中定義
1
2
3
|
'components' => [ 'cache' => [ 'class' => 'yii\caching\filecache' , ],], |
這里的自由度就出現了,現在這個配置,是文件緩存,也就是不管是數據緩存還是頁面緩存,都是保存在文件里的
根據源碼 public $cachepath = '@runtime/cache';
緩存的文件是放在runtime/cache文件夾的
那么問題就出現了,磁盤的性能是有瓶頸的,文件讀寫會影響緩存性能。
目前可選的緩存有
- yii\caching\apccache,apc擴展
- yii\caching\dbcache,數據庫緩存
- yii\caching\dummycache,假的緩存,就是現在沒條件上緩存先把坑占上
- yii\caching\filecache,文件緩存
- yii\caching\memcache,使用 php memcache 和 memcached 擴展
- yii\redis\cache,redis
- yii\caching\wincache,使用 php wincache 擴展
- yii\caching\xcache,使用 php xcache擴展
- yii\caching\zenddatacache,使用zend data cache
總結
我在本文中,通過漸進的方式,講了如何使用yii2的緩存組件,對于一般的使用者來講,已經涵蓋了超過九成的坑。
如果你正在學習php,希望你收藏這篇文章,這會對你以后有所幫助。
到此這篇關于php之深入學習yii2緩存cache組件詳細講解的文章就介紹到這了,更多相關php之深入學習yii2緩存cache組件內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://blog.csdn.net/diandianxiyu_geek/article/details/118507284