[TOC]
# 使用緩存提高性能
Phalcon提供`Phalcon\Cache`類,允許更快地訪問常用或已處理的數據。`Phalcon\Cache`是用C語言編寫的,在從后端獲取項目時可以實現更高的性能并減少開銷。此類使用前端和后端組件的內部結構。前端組件充當輸入源或接口,而后端組件為類提供存儲選項。
## 什么時候使用緩存?
雖然這個組件非常快,但在不需要的情況下實現它可能會導致性能損失而不是獲得。我們建議您在使用緩存之前檢查此案例:
* 您正在進行復雜的計算,每次返回相同的結果(不經常更改)
* 您正在使用大量幫助程序,并且生成的輸出幾乎總是相同的
* 您正在不斷訪問數據庫數據,這些數據很少更改
>[warning] **NOTE** 即使在實現緩存之后,您也應該檢查緩存在一段時間內的命中率。 這可以很容易地完成,特別是在Memcache或Apc的情況下,使用后端提供的相關工具。
## 緩存行為
緩存過程分為兩部分:
* **前端**:此部分負責檢查密鑰是否已過期,并在存儲之前和從后端檢索數據后對數據執行其他轉換
* **后端**: 該部分負責通信,寫入/讀取前端所需的數據。
## 工廠
實例化前端或后端適配器可以通過兩種方式實現:
傳統方式
```php
<?php
use Phalcon\Cache\Backend\File as BackFile;
use Phalcon\Cache\Frontend\Data as FrontData;
// 創建輸出前端。將文件緩存2天
$frontCache = new FrontData(
[
'lifetime' => 172800,
]
);
// 創建將從“輸出”緩存到“文件”后端的組件
// 設置緩存文件目錄 - 將'/'保留在文件夾值的末尾非常重要
$cache = new BackFile(
$frontCache,
[
'cacheDir' => '../app/cache/',
]
);
```
或使用Factory對象,如下所示:
```php
<?php
use Phalcon\Cache\Frontend\Factory as FFactory;
use Phalcon\Cache\Backend\Factory as BFactory;
$options = [
'lifetime' => 172800,
'adapter' => 'data',
];
$frontendCache = FFactory::load($options);
$options = [
'cacheDir' => '../app/cache/',
'prefix' => 'app-data',
'frontend' => $frontendCache,
'adapter' => 'file',
];
$backendCache = BFactory::load($options);
```
## 緩存輸出片段
輸出片段是一段HTML或文本,按原樣緩存并按原樣返回。從`ob_ *`函數或PHP輸出自動捕獲輸出,以便將其保存在緩存中。以下示例演示了此類用法。它接收PHP生成的輸出并將其存儲到文件中。該文件的內容每172,800秒(2天)刷新一次。
這種緩存機制的實現允許我們通過在調用這段代碼時不執行輔助`Phalcon\Tag::linkTo()`調用來獲得性能。
```php
<?php
use Phalcon\Tag;
use Phalcon\Cache\Backend\File as BackFile;
use Phalcon\Cache\Frontend\Output as FrontOutput;
// 創建輸出前端。將文件緩存2天
$frontCache = new FrontOutput(
[
'lifetime' => 172800,
]
);
// 創建將從“輸出”緩存到“文件”后端的組件
// 設置緩存文件目錄 - 將'/'保留在文件夾值的末尾非常重要
$cache = new BackFile(
$frontCache,
[
'cacheDir' => '../app/cache/',
]
);
// 獲取/設置緩存文件為../app/cache/my-cache.html
$content = $cache->start('my-cache.html');
// 如果 $content 為null,則將為緩存生成內容
if ($content === null) {
// 打印日期和時間
echo date('r');
// 生成注冊操作的鏈接
echo Tag::linkTo(
[
'user/signup',
'Sign Up',
'class' => 'signup-button',
]
);
// 將輸出存儲到緩存文件中
$cache->save();
} else {
// 回顯緩存的輸出
echo $content;
}
```
>[warning] **NOTE** 在上面的示例中,我們的代碼保持不變,將輸出回顯給用戶,就像之前一樣。 我們的緩存組件透明地捕獲該輸出并將其存儲在緩存文件中(當生成緩存時)或者將其發送回從先前調用預編譯的用戶,從而避免昂貴的操作。
## 緩存任意數據
僅緩存數據對于您的應用程序同樣重要。緩存可以通過重用常用(但未更新)的數據來減少數據庫負載,從而加快應用程序的速度。
### File后端示例
其中一個緩存適配器是`File`。此適配器的唯一關鍵區域是緩存文件的存儲位置。這由`cacheDir`選項控制,該選項必須在其末尾加上反斜杠。
```php
<?php
use Phalcon\Cache\Backend\File as BackFile;
use Phalcon\Cache\Frontend\Data as FrontData;
// 創建輸出前端。將文件緩存2天
$frontCache = new FrontData(
[
'lifetime' => 172800,
]
);
// 創建將從“輸出”緩存到“文件”后端的組件
// 設置緩存文件目錄 - 將'/'保留在文件夾值的末尾非常重要
$cache = new BackFile(
$frontCache,
[
'cacheDir' => '../app/cache/',
]
);
$cacheKey = 'robots_order_id.cache';
// 嘗試獲取緩存記錄
$robots = $cache->get($cacheKey);
if ($robots === null) {
// 由于緩存過期或數據不存在,$robots為 null
// 進行數據庫調用并填充變量
$robots = Robots::find(
[
'order' => 'id',
]
);
// 將其存儲在緩存中
$cache->save($cacheKey, $robots);
}
// 使用 $robots :)
foreach ($robots as $robot) {
echo $robot->name, '\n';
}
```
### Memcached后端示例
當我們使用Memcached后端時,上面的示例略有變化(特別是在配置方面)。
```php
<?php
use Phalcon\Cache\Frontend\Data as FrontData;
use Phalcon\Cache\Backend\Libmemcached as BackMemCached;
// 緩存數據一小時
$frontCache = new FrontData(
[
'lifetime' => 3600,
]
);
// 創建將“數據”緩存到“Memcached”后端的組件
// Memcached連接設置
$cache = new BackMemCached(
$frontCache,
[
'servers' => [
[
'host' => '127.0.0.1',
'port' => '11211',
'weight' => '1',
]
]
]
);
$cacheKey = 'robots_order_id.cache';
// 嘗試獲取緩存記錄
$robots = $cache->get($cacheKey);
if ($robots === null) {
// 由于緩存過期或數據不存在,$robots為 null
// 進行數據庫調用并填充變量
$robots = Robots::find(
[
'order' => 'id',
]
);
// 將其存儲在緩存中
$cache->save($cacheKey, $robots);
}
// 使用 $robots :)
foreach ($robots as $robot) {
echo $robot->name, '\n';
}
```
>[warning] **NOTE** 調用 <code>save()</code> 將返回一個布爾值,表示成功(true)或失敗(false)。 根據您使用的后端,您需要查看相關日志以識別故障。
## 查詢緩存
添加到緩存的元素由key唯一標識。對于File后端,key是實際文件名。要從緩存中檢索數據,我們只需使用唯一key調用它。如果key不存在,則get方法將返回null。
```php
<?php
// 按key 'myProducts'檢索產品
$products = $cache->get('myProducts');
```
如果您想知道緩存中存儲了哪些key,可以調用`queryKeys`方法:
```php
<?php
// 查詢緩存中使用的所有的key
$keys = $cache->queryKeys();
foreach ($keys as $key) {
$data = $cache->get($key);
echo 'Key=', $key, ' Data=', $data;
}
// 以“my-prefix”開頭的緩存中的查詢key
$keys = $cache->queryKeys('my-prefix');
```
## 從緩存中刪除數據
有時您需要強制使緩存條目無效(由于緩存數據中的更新)。唯一的要求是知道數據存儲的key。
```php
<?php
// 刪除具有特定key的項目
$cache->delete('someKey');
$keys = $cache->queryKeys();
// 從緩存中刪除所有項目
foreach ($keys as $key) {
$cache->delete($key);
}
```
## 檢查緩存是否存在
可以使用給定的key檢查緩存是否已存在:
```php
<?php
if ($cache->exists('someKey')) {
echo $cache->get('someKey');
} else {
echo 'Cache does not exists!';
}
```
## 生命周期
生命周期是緩存可以在沒有過期的情況下生存的時間(以秒為單位)。默認情況下,所有創建的緩存都使用前端創建中設置的生存期。您可以在從緩存中創建或檢索數據時設置特定生命周期:
檢索時設置生命周期:
```php
<?php
$cacheKey = 'my.cache';
// 獲取結果時設置緩存
$robots = $cache->get($cacheKey, 3600);
if ($robots === null) {
$robots = 'some robots';
// 將其存儲在緩存中
$cache->save($cacheKey, $robots);
}
```
保存時設置生命周期:
```php
<?php
$cacheKey = 'my.cache';
$robots = $cache->get($cacheKey);
if ($robots === null) {
$robots = 'some robots';
// 保存數據時設置緩存
$cache->save($cacheKey, $robots, 3600);
}
```
## 多級緩存
緩存組件的此功能允許開發人員實現多級緩存。這個新功能非常有用,因為您可以將相同的數據保存在具有不同生命周期的多個緩存位置中,首先從具有較快適配器的緩存中讀取,然后以最慢的一個讀取直到數據到期:
```php
<?php
use Phalcon\Cache\Multiple;
use Phalcon\Cache\Backend\Apc as ApcCache;
use Phalcon\Cache\Backend\File as FileCache;
use Phalcon\Cache\Frontend\Data as DataFrontend;
use Phalcon\Cache\Backend\Memcache as MemcacheCache;
$ultraFastFrontend = new DataFrontend(
[
'lifetime' => 3600,
]
);
$fastFrontend = new DataFrontend(
[
'lifetime' => 86400,
]
);
$slowFrontend = new DataFrontend(
[
'lifetime' => 604800,
]
);
// 后端從最快到最慢注冊
$cache = new Multiple(
[
new ApcCache(
$ultraFastFrontend,
[
'prefix' => 'cache',
]
),
new MemcacheCache(
$fastFrontend,
[
'prefix' => 'cache',
'host' => 'localhost',
'port' => '11211',
]
),
new FileCache(
$slowFrontend,
[
'prefix' => 'cache',
'cacheDir' => '../app/cache/',
]
),
]
);
// 保存,保存在每個后端
$cache->save('my-key', $data);
```
## 前端適配器
可用作緩存的接口或輸入源的前端適配器是:
| 適配器 | 描述 |
| ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Phalcon\Cache\Frontend\Output` | 從標準PHP輸出中讀取輸入數據。 |
| `Phalcon\Cache\Frontend\Data` | 它用于緩存任何類型的PHP數據(大數組,對象,文本等)。數據在存儲在后端之前被序列化。 |
| `Phalcon\Cache\Frontend\Base64` | 它用于緩存二進制數據。在存儲在后端之前,使用`base64_encode`對數據進行序列化。 |
| `Phalcon\Cache\Frontend\Json` | 數據在存儲在后端之前以JSON編碼。檢索后解碼。此前端對于與其他語言或框架共享數據非常有用。 |
| `Phalcon\Cache\Frontend\Igbinary` | 它用于緩存任何類型的PHP數據(大數組,對象,文本等)。在存儲在后端之前,使用`Igbinary`對數據進行序列化。 |
| `Phalcon\Cache\Frontend\None` | 它用于緩存任何類型的PHP數據而無需序列化它們。 |
### 實現自己的前端適配器
必須實現`Phalcon\Cache\FrontendInterface` 接口才能創建自己的前端適配器或擴展現有前端適配器。
## 后端適配器
可用于存儲緩存數據的后端適配器是:
| 適配器 | 描述 | 信息 | 需要的擴展 |
| ------------------------------------ | ---------------------------------------------------- | ----------------------------------------- | -------------------------------------------------- |
| `Phalcon\Cache\Backend\Apc` | 將數據存儲到Alternative PHP Cache(APC) | [APC](http://php.net/apc) | [APC](http://pecl.php.net/package/APC) |
| `Phalcon\Cache\Backend\Apcu` |將數據存儲到APCu(沒有操作碼緩存的APC) | [APCu](http://php.net/apcu) | [APCu](http://pecl.php.net/package/APCu) |
| `Phalcon\Cache\Backend\File` | 將數據存儲到本地純文件。 | | |
| `Phalcon\Cache\Backend\Libmemcached` | 將數據存儲到memcached服務器。 | [Memcached](http://www.php.net/memcached) | [Memcached](http://pecl.php.net/package/memcached) |
| `Phalcon\Cache\Backend\Memcache` | 將數據存儲到memcached服務器。 | [Memcache](http://www.php.net/memcache) | [Memcache](http://pecl.php.net/package/memcache) |
| `Phalcon\Cache\Backend\Memory` | 將數據存儲到內存 | | |
| `Phalcon\Cache\Backend\Mongo` | 將數據存儲到Mongo數據庫。 | [MongoDB](http://mongodb.org/) | [Mongo](http://mongodb.org/) |
| `Phalcon\Cache\Backend\Redis` | 將數據存儲到Redis. | [Redis](http://redis.io/) | [Redis](http://pecl.php.net/package/redis) |
| `Phalcon\Cache\Backend\Xcache` | 將數據存儲到XCache. | [XCache](http://xcache.lighttpd.net/) | [XCache](http://pecl.php.net/package/xcache) |
>[warning] **NOTE** 在PHP 7中使用基于phalcon apc的適配器類,您需要從pecl安裝`apcu`和`apcu_bc`包。現在在Phalcon
中,您可以將`*\Apc`類切換為`*\ Apcu`并刪除`apcu_bc`。請記住,在Phalcon 4中,我們很可能會刪除所有`*\Apc`類。
### 工廠
有許多后端適配器(請參閱后端適配器)。您使用的那個將取決于您的應用程序的需求。下面的示例使用`adapter`選項加載后端緩存適配器類,如果前端將作為數組提供,它將調用前端緩存工廠
```php
<?php
use Phalcon\Cache\Backend\Factory;
use Phalcon\Cache\Frontend\Data;
$options = [
'prefix' => 'app-data',
'frontend' => new Data(),
'adapter' => 'apc',
];
$backendCache = Factory::load($options);
```
### 實現自己的后端適配器
必須實現 `Phalcon\Cache\BackendInterface` 接口才能創建自己的后端適配器或擴展現有的后端適配器。
### File后端選項
此后端將緩存的內容存儲到本地服務器的文件中。此后端的可用選項包括:
| 選項 | 描述 |
| ---------- | ------------------------------------ |
| `prefix` | 自動添加到緩存key的前綴。 |
| `cacheDir` | 一個可寫目錄,將在其上放置緩存文件。 |
### Libmemcached后端選項
此后端將緩存的內容存儲在memcached服務器上。每個默認持久性memcached連接池都使用。此后端的可用選項包括:
**常規選項**
| 選項 | 描述 |
| --------------- | ------------------------------------------------------------ |
| `statsKey` | 用于跟蹤緩存的key。 |
| `prefix` | 自動添加到緩存key的前綴。 |
| `persistent_id` | 要創建在請求之間保持不變的實例,請使用persistent_id為實例指定唯一ID。 |
**服務端選項**
| 選項 | 描述 |
| -------- | ------------------------------------------------------------ |
| `host` | The `memcached` host. |
| `port` | The `memcached` port. |
| `weight` | 要創建在請求之間保持不變的實例,請使用persistent_id為實例指定唯一ID。 |
**客戶端選項**
用于設置Memcached選項。有關更多信息,請參閱`Memcached::setOptions`。
**示例**
```php
<?php
use Phalcon\Cache\Backend\Libmemcached;
use Phalcon\Cache\Frontend\Data as FrontData;
// 緩存數據2天
$frontCache = new FrontData(
[
'lifetime' => 172800,
]
);
// 創建緩存設置memcached連接選項
$cache = new Libmemcached(
$frontCache,
[
'servers' => [
[
'host' => '127.0.0.1',
'port' => 11211,
'weight' => 1,
],
],
'client' => [
\Memcached::OPT_HASH => \Memcached::HASH_MD5,
\Memcached::OPT_PREFIX_KEY => 'prefix.',
],
'persistent_id' => 'my_app_cache',
]
);
```
### Memcache后端選項
此后端將緩存的內容存儲在memcached服務器上。此后端的可用選項包括:
| 選項 | 描述 |
| ------------ | --------------------------- |
| `prefix` | 自動添加到緩存key的前綴。 |
| `host` | memcached host地址。 |
| `port` | memcached端口。 |
| `persistent` | 創建與memcached的持久連接? |
### APC后端選項
此后端將緩存內容存儲在Alternative PHP Cache([APC](http://php.net/apc))上。此后端的可用選項包括:
| 選項 | 描述 |
| -------- | ------------------------- |
| `prefix` | 自動添加到緩存key的前綴。 |
### APCU后端選項
此后端將緩存內容存儲在Alternative PHP Cache([APCU](http://php.net/apcu))上。此后端的可用選項包括:
| 選項 | 描述 |
| -------- | ------------------------- |
| `prefix` | 自動添加到緩存key的前綴。 |
### Mongo后端選項
此后端將緩存內容存儲在MongoDB服務器([MongoDB](http://mongodb.org/))上。此后端的可用選項包括:
| 選項 | 描述 |
| ------------ | ------------------------- |
| `prefix` | 自動添加到緩存key的前綴。 |
| `server` | MongoDB連接字符串。 |
| `db` | Mongo數據庫名稱。 |
| `collection` | Mongo集合在數據庫中。 |
### XCache后端選項
此后端將在XCache([XCache](http://xcache.lighttpd.net/))上存儲緩存的內容。此后端的可用選項包括:
| 選項 | 描述 |
| -------- | ------------------------- |
| `prefix` | 自動添加到緩存key的前綴。 |
### Redis后端選項
此后端將緩存內容存儲在Redis服務器([Redis](http://redis.io/))上。此后端的可用選項包括:
| 選項 | 描述 |
| ------------ | ------------------------------------------------- |
| `prefix` | 自動添加到緩存key的前綴。 |
| `host` | Redis host地址 |
| `port` | Redis 端口 |
| `auth` | 用于向受密碼保護的Redis服務器進行身份驗證的密碼。 |
| `persistent` | 創建與Redis的持久連接。 |
| `index` | 要使用的Redis數據庫的索引。 |
Phalcon孵化器中有更多適用于此組件的適配器
- 常規
- Welcome
- 貢獻
- 生成回溯
- 測試重現
- 單元測試
- 入門
- 安裝
- Web服務器設置
- WAMP
- XAMPP
- 教程
- 基礎教程
- 教程:創建一個簡單的REST API
- 教程:V?kuró
- 提升性能
- 教程:INVO
- 開發環境
- Phalcon Compose (Docker)
- Nanobox
- Phalcon Box (Vagrant)
- 開發工具
- Phalcon開發者工具的安裝
- Phalcon開發者工具的使用
- 調試應用程序
- 核心
- MVC應用
- 微應用
- 創建命令行(CLI)應用程序
- 依賴注入與服務定位
- MVC架構
- 服務
- 使用緩存提高性能
- 讀取配置
- 上下文轉義
- 類加載器
- 使用命名空間
- 日志
- 隊列
- 數據庫
- 數據庫抽象層
- Phalcon查詢語言(PHQL)
- ODM(對象文檔映射器)
- 使用模型
- 模型行為
- ORM緩存
- 模型事件
- 模型元數據
- 模型關系
- 模型事務
- 驗證模型
- 數據庫遷移
- 分頁
- 前端
- Assets管理
- 閃存消息
- 表單
- 圖像
- 視圖助手(標簽)
- 使用視圖
- Volt:模板引擎
- 業務邏輯
- 訪問控制列表(ACL)
- 注解解析器
- 控制器
- 調度控制器
- 事件管理器
- 過濾與清理
- 路由
- 在session中存儲數據
- 生成URL和路徑
- 驗證
- HTTP
- Cookies管理
- 請求環境
- 返回響應
- 安全
- 加密/解密
- 安全
- 國際化
- 國際化
- 多語言支持