鍍金池/ 教程/ PHP/ 數(shù)據(jù)緩存
查詢構(gòu)建器
HTTP 緩存
單元測試
資源
數(shù)據(jù)庫遷移
Fixtures
收集列表輸入
認(rèn)證
助手類
緩存
數(shù)據(jù)緩存
最佳安全實踐
響應(yīng)格式
使用 Gii 生成代碼
服務(wù)定位器
性能優(yōu)化
資源
多模型的復(fù)合表單
控制器
Html 幫助類
運行機制概述
快速入門
屬性(Property)
使用表單
配置測試環(huán)境
數(shù)據(jù)提供者
使用數(shù)據(jù)庫
授權(quán)
輸入驗證
類自動加載(Autoloading)
版本
響應(yīng)
Sessions 和 Cookies
數(shù)組助手類
創(chuàng)建你自己的應(yīng)用程序結(jié)構(gòu)
文件上傳
路由
收發(fā)郵件
模型
小部件
更上一層樓
頁面緩存
請求
片段緩存
排序
處理密碼
數(shù)據(jù)小部件
模塊
事件
控制器
從 Yii 1.1 升級
應(yīng)用組件
驗收測試
入口腳本
總覽
Url 幫助類
行為
速率限制
控制臺命令
依賴注入容器
視圖
功能測試
錯誤處理
過濾器
主題
應(yīng)用主體
引入第三方代碼
共享托管環(huán)境
測試
擴展
路由
使用模板引擎
核心驗證器(Core Validators)
分頁
數(shù)據(jù)庫訪問 (DAO)
配置
創(chuàng)建表單
日志
安裝 Yii
客戶端腳本使用
組件(Component)
說聲 Hello
運行應(yīng)用
數(shù)據(jù)格式器
認(rèn)證
錯誤處理
別名(Aliases)
Active Record
啟動引導(dǎo)(Bootstrapping)
國際化

數(shù)據(jù)緩存

數(shù)據(jù)緩存是指將一些 PHP 變量存儲到緩存中,使用時再從緩存中取回。它也是更高級緩存特性的基礎(chǔ),例如查詢緩存和內(nèi)容緩存。

如下代碼是一個典型的數(shù)據(jù)緩存使用模式。其中 $cache 指向緩存組件

// 嘗試從緩存中取回 $data 
$data = $cache->get($key);

if ($data === false) {

    // $data 在緩存中沒有找到,則重新計算它的值

    // 將 $data 存放到緩存供下次使用
    $cache->set($key, $data);
}

// 這兒 $data 可以使用了。

緩存組件

數(shù)據(jù)緩存需要緩存組件提供支持,它代表各種緩存存儲器,例如內(nèi)存,文件,數(shù)據(jù)庫。

緩存組件通常注冊為應(yīng)用程序組件,這樣它們就可以在全局進行配置與訪問。如下代碼演示了如何配置應(yīng)用程序組件 cache 使用兩個 memcached 服務(wù)器:

'components' => [
    'cache' => [
        'class' => 'yii\caching\MemCache',
        'servers' => [
            [
                'host' => 'server1',
                'port' => 11211,
                'weight' => 100,
            ],
            [
                'host' => 'server2',
                'port' => 11211,
                'weight' => 50,
            ],
        ],
    ],
],

然后就可以通過 Yii::$app->cache 訪問上面的緩存組件了。

由于所有緩存組件都支持同樣的一系列 API ,并不需要修改使用緩存的業(yè)務(wù)代碼就能直接替換為其他底層緩存組件,只需在應(yīng)用配置中重新配置一下就可以。例如,你可以將上述配置修改為使用 [[yii\caching\ApcCache|APC cache]]:

'components' => [
    'cache' => [
        'class' => 'yii\caching\ApcCache',
    ],
],

Tip: 你可以注冊多個緩存組件,很多依賴緩存的類默認(rèn)調(diào)用名為 cache 的組件(例如 [[yii\web\UrlManager]])。

支持的緩存存儲器

Yii 支持一系列緩存存儲器,概況如下:

  • [[yii\caching\ApcCache]]:使用 PHP APC 擴展。這個選項可以認(rèn)為是集中式應(yīng)用程序環(huán)境中(例如:單一服務(wù)器,沒有獨立的負(fù)載均衡器等)最快的緩存方案。
  • [[yii\caching\DbCache]]:使用一個數(shù)據(jù)庫的表存儲緩存數(shù)據(jù)。要使用這個緩存,你必須創(chuàng)建一個與 [[yii\caching\DbCache::cacheTable]] 對應(yīng)的表。
  • [[yii\caching\DummyCache]]: 僅作為一個緩存占位符,不實現(xiàn)任何真正的緩存功能。這個組件的目的是為了簡化那些需要查詢緩存有效性的代碼。例如,在開發(fā)中如果服務(wù)器沒有實際的緩存支持,用它配置一個緩存組件。一個真正的緩存服務(wù)啟用后,可以再切換為使用相應(yīng)的緩存組件。兩種條件下你都可以使用同樣的代碼 Yii::$app->cache->get($key) 嘗試從緩存中取回數(shù)據(jù)而不用擔(dān)心 Yii::$app->cache 可能是 null。
  • [[yii\caching\FileCache]]:使用標(biāo)準(zhǔn)文件存儲緩存數(shù)據(jù)。這個特別適用于緩存大塊數(shù)據(jù),例如一個整頁的內(nèi)容。
  • [[yii\caching\MemCache]]:使用 PHP memcachememcached 擴展。這個選項被看作分布式應(yīng)用環(huán)境中(例如:多臺服務(wù)器,有負(fù)載均衡等)最快的緩存方案。
  • [[yii\redis\Cache]]:實現(xiàn)了一個基于 Redis 鍵值對存儲器的緩存組件(需要 redis 2.6.12 及以上版本的支持 )。
  • [[yii\caching\WinCache]]:使用 PHP WinCache另可參考)擴展.
  • [[yii\caching\XCache]]:使用 PHP XCache擴展。
  • [[yii\caching\ZendDataCache]]:使用 Zend Data Cache 作為底層緩存媒介。

Tip: 你可以在同一個應(yīng)用程序中使用不同的緩存存儲器。一個常見的策略是使用基于內(nèi)存的緩存存儲器存儲小而常用的數(shù)據(jù)(例如:統(tǒng)計數(shù)據(jù)),使用基于文件或數(shù)據(jù)庫的緩存存儲器存儲大而不太常用的數(shù)據(jù)(例如:網(wǎng)頁內(nèi)容)。

緩存 API

所有緩存組件都有同樣的基類 [[yii\caching\Cache]] ,因此都支持如下 API:

  • [[yii\caching\Cache::get()|get()]]:通過一個指定的鍵(key)從緩存中取回一項數(shù)據(jù)。如果該項數(shù)據(jù)不存在于緩存中或者已經(jīng)過期/失效,則返回值 false。
  • [[yii\caching\Cache::set()|set()]]:將一項數(shù)據(jù)指定一個鍵,存放到緩存中。
  • [[yii\caching\Cache::add()|add()]]:如果緩存中未找到該鍵,則將指定數(shù)據(jù)存放到緩存中。
  • [[yii\caching\Cache::mget()|mget()]]:通過指定的多個鍵從緩存中取回多項數(shù)據(jù)。
  • [[yii\caching\Cache::mset()|mset()]]:將多項數(shù)據(jù)存儲到緩存中,每項數(shù)據(jù)對應(yīng)一個鍵。
  • [[yii\caching\Cache::madd()|madd()]]:將多項數(shù)據(jù)存儲到緩存中,每項數(shù)據(jù)對應(yīng)一個鍵。如果某個鍵已經(jīng)存在于緩存中,則該項數(shù)據(jù)會被跳過。
  • [[yii\caching\Cache::exists()|exists()]]:返回一個值,指明某個鍵是否存在于緩存中。
  • [[yii\caching\Cache::delete()|delete()]]:通過一個鍵,刪除緩存中對應(yīng)的值。
  • [[yii\caching\Cache::flush()|flush()]]:刪除緩存中的所有數(shù)據(jù)。

有些緩存存儲器如 MemCache,APC 支持以批量模式取回緩存值,這樣可以節(jié)省取回緩存數(shù)據(jù)的開支。 [[yii\caching\Cache::mget()|mget()]] 和 [[yii\caching\Cache::madd()|madd()]] API 提供對該特性的支持。如果底層緩存存儲器不支持該特性,Yii 也會模擬實現(xiàn)。

由于 [[yii\caching\Cache]] 實現(xiàn)了 PHP ArrayAccess 接口,緩存組件也可以像數(shù)組那樣使用,下面是幾個例子:

$cache['var1'] = $value1;  // 等價于: $cache->set('var1', $value1);
$value2 = $cache['var2'];  // 等價于: $value2 = $cache->get('var2');

緩存鍵

存儲在緩存中的每項數(shù)據(jù)都通過鍵作唯一識別。當(dāng)你在緩存中存儲一項數(shù)據(jù)時,必須為它指定一個鍵,稍后從緩存中取回數(shù)據(jù)時,也需要提供相應(yīng)的鍵。

你可以使用一個字符串或者任意值作為一個緩存鍵。當(dāng)鍵不是一個字符串時,它將會自動被序列化為一個字符串。

定義一個緩存鍵常見的一個策略就是在一個數(shù)組中包含所有的決定性因素。例如,[[yii\db\Schema]] 使用如下鍵存儲一個數(shù)據(jù)表的結(jié)構(gòu)信息。

[
    __CLASS__,              // 結(jié)構(gòu)類名
    $this->db->dsn,         // 數(shù)據(jù)源名稱
    $this->db->username,    // 數(shù)據(jù)庫登錄用戶名
    $name,                  // 表名
];

如你所見,該鍵包含了可唯一指定一個數(shù)據(jù)庫表所需的所有必要信息。

當(dāng)同一個緩存存儲器被用于多個不同的應(yīng)用時,應(yīng)該為每個應(yīng)用指定一個唯一的緩存鍵前綴以避免緩存鍵沖突??梢酝ㄟ^配置 [[yii\caching\Cache::keyPrefix]] 屬性實現(xiàn)。例如,在應(yīng)用配置中可以編寫如下代碼:

'components' => [
    'cache' => [
        'class' => 'yii\caching\ApcCache',
        'keyPrefix' => 'myapp',       // 唯一鍵前綴
    ],
],

為了確?;ネㄐ?,此處只能使用字母和數(shù)字。

緩存過期

默認(rèn)情況下,緩存中的數(shù)據(jù)會永久存留,除非它被某些緩存策略強制移除(例如:緩存空間已滿,最老的數(shù)據(jù)會被移除)。要改變此特性,你可以在調(diào)用 [[yii\caching\Cache::set()|set()]] 存儲一項數(shù)據(jù)時提供一個過期時間參數(shù)。該參數(shù)代表這項數(shù)據(jù)在緩存中可保持有效多少秒。當(dāng)你調(diào)用 [[yii\caching\Cache::get()|get()]] 取回數(shù)據(jù)時,如果它已經(jīng)過了超時時間,該方法將返回 false,表明在緩存中找不到這項數(shù)據(jù)。例如:

// 將數(shù)據(jù)在緩存中保留 45 秒
$cache->set($key, $data, 45);

sleep(50);

$data = $cache->get($key);
if ($data === false) {
    // $data 已過期,或者在緩存中找不到
}

緩存依賴

除了超時設(shè)置,緩存數(shù)據(jù)還可能受到緩存依賴的影響而失效。例如,[[yii\caching\FileDependency]] 代表對一個文件修改時間的依賴。這個依賴條件發(fā)生變化也就意味著相應(yīng)的文件已經(jīng)被修改。因此,緩存中任何過期的文件內(nèi)容都應(yīng)該被置為失效狀態(tài),對 [[yii\caching\Cache::get()|get()]] 的調(diào)用都應(yīng)該返回 false。

緩存依賴用 [[yii\caching\Dependency]] 的派生類所表示。當(dāng)調(diào)用 [[yii\caching\Cache::set()|set()]] 在緩存中存儲一項數(shù)據(jù)時,可以同時傳遞一個關(guān)聯(lián)的緩存依賴對象。例如:

// 創(chuàng)建一個對 example.txt 文件修改時間的緩存依賴
$dependency = new \yii\caching\FileDependency(['fileName' => 'example.txt']);

// 緩存數(shù)據(jù)將在 30 秒后超時
// 如果 example.txt 被修改,它也可能被更早地置為失效狀態(tài)。
$cache->set($key, $data, 30, $dependency);

// 緩存會檢查數(shù)據(jù)是否已超時。
// 它還會檢查關(guān)聯(lián)的依賴是否已變化。
// 符合任何一個條件時都會返回 false。
$data = $cache->get($key);

下面是可用的緩存依賴的概況:

  • [[yii\caching\ChainedDependency]]:如果依賴鏈上任何一個依賴產(chǎn)生變化,則依賴改變。
  • [[yii\caching\DbDependency]]:如果指定 SQL 語句的查詢結(jié)果發(fā)生了變化,則依賴改變。
  • [[yii\caching\ExpressionDependency]]:如果指定的 PHP 表達式執(zhí)行結(jié)果發(fā)生變化,則依賴改變。
  • [[yii\caching\FileDependency]]:如果文件的最后修改時間發(fā)生變化,則依賴改變。
  • [[yii\caching\GroupDependency]]:將一項緩存數(shù)據(jù)標(biāo)記到一個組名,你可以通過調(diào)用 [[yii\caching\GroupDependency::invalidate()]] 一次性將相同組名的緩存全部置為失效狀態(tài)。

查詢緩存

查詢緩存是一個建立在數(shù)據(jù)緩存之上的特殊緩存特性。它用于緩存數(shù)據(jù)庫查詢的結(jié)果。

查詢緩存需要一個 [[yii\db\Connection|數(shù)據(jù)庫連接]] 和一個有效的 cache 應(yīng)用組件。查詢緩存的基本用法如下,假設(shè) $db 是一個 [[yii\db\Connection]] 實例:

$duration = 60;     // 緩存查詢結(jié)果 60 秒
$dependency = ...;  // 可選的緩存依賴

$db->beginCache($duration, $dependency);

// ...這兒執(zhí)行數(shù)據(jù)庫查詢...

$db->endCache();

如你所見,beginCache()endCache() 中間的任何查詢結(jié)果都會被緩存起來。如果緩存中找到了同樣查詢的結(jié)果,則查詢會被跳過,直接從緩存中提取結(jié)果。

查詢緩存可以用于 ActiveRecordDAO。

Info: 有些 DBMS (例如:MySQL)也支持?jǐn)?shù)據(jù)庫服務(wù)器端的查詢緩存。你可以選擇使用任一查詢緩存機制。上文所述的查詢緩存的好處在于你可以指定更靈活的緩存依賴因此可能更加高效。

配置

查詢緩存有兩個通過 [[yii\db\Connection]] 設(shè)置的配置項:

  • [[yii\db\Connection::queryCacheDuration|queryCacheDuration]]: 查詢結(jié)果在緩存中的有效期,以秒表示。如果在調(diào)用 [[yii\db\Connection::beginCache()]] 時傳遞了一個顯式的時值參數(shù),則配置中的有效期時值會被覆蓋。
  • [[yii\db\Connection::queryCache|queryCache]]: 緩存應(yīng)用組件的 ID。默認(rèn)為 'cache'。只有在設(shè)置了一個有效的緩存應(yīng)用組件時,查詢緩存才會有效。

限制條件

當(dāng)查詢結(jié)果中含有資源句柄時,查詢緩存無法使用。例如,在有些 DBMS 中使用了 BLOB 列的時候,緩存結(jié)果會為該數(shù)據(jù)列返回一個資源句柄。

有些緩存存儲器有大小限制。例如,memcache 限制每條數(shù)據(jù)最大為 1MB。因此,如果查詢結(jié)果的大小超出了該限制,則會導(dǎo)致緩存失敗。

上一篇:別名(Aliases)下一篇:收發(fā)郵件