# 使用緩存提高性能(Improving Performance with Cache)
Phalcon提供的[Phalcon\\Cache](http://docs.iphalcon.cn/reference/cache.html#)類可以更快地接入獲取使用頻繁或者已經被處理的數據。[Phalcon\\Cache](http://docs.iphalcon.cn/reference/cache.html#)是用C來編寫的,因此有著更高的性能并且能夠減少從后端獲取昂價資源所帶來的負載。 這個類使用了由前端和后端組件組成的內部結構。前端組件如輸入源或者接口,后端組件則為這個類提供了存儲的選項。
## 什么情況下使用緩存?(When to implement cache?)
盡管這個組件運行非常快速,但如果不加考慮就使用它會適得其反,特別在不需要或者不適宜使用緩存時。 我們建議你在使用緩存前核對一下場景:
* 你正在進行復雜的運算,并且每次都返回相同的結果(或者變動很少)
* 你正在使用大量的插件生成大部分時間幾乎都是相同的頁面輸出
* 你正在頻繁地接入數據庫并且這些數據變動甚少
> *溫馨提示*即使使用了這些緩存,你仍然應該定期檢測緩存的命中率。 通過后臺提供的相關工具,這一點很容易做得到,特別是使用Memcache或者APC時。
## 緩存行為(Caching Behavior)
緩存流程可以分為兩部分:
* **前端**: 此部分負責檢測是否key已失效并且在保存數據和抓取數據后提供額外的轉換操作。
* **后端**: 此部分負責通訊,并根據前端進行數據的讀/寫。
## 緩存輸出片段(Caching Output Fragments)
輸出片段是指一小塊緩存和返回都一樣的HTML或者文本內容。輸出的內容應該是能自動 被 ob\_\* 函數捕獲或者直接是PHP輸出,這樣才能緩存起來。以下實例演示了這樣的使用。 它接收PHP生成的頁面輸出并保存在一個文件里面。緩存文件的內容每隔172800秒(2天)刷新一次。
使用這個緩存機制,無論何時調用這塊代碼,我們都可以通過避免重復執行輔助插件`Phalcon\Tag::linkTo()`從而獲得更高的性能。
~~~
<?php
use Phalcon\Tag;
use Phalcon\Cache\Backend\File as BackFile;
use Phalcon\Cache\Frontend\Output as FrontOutput;
// Create an Output frontend. Cache the files for 2 days
$frontCache = new FrontOutput(
[
"lifetime" => 172800,
]
);
// Create the component that will cache from the "Output" to a "File" backend
// Set the cache file directory - it's important to keep the "/" at the end of
// the value for the folder
$cache = new BackFile(
$frontCache,
[
"cacheDir" => "../app/cache/",
]
);
// Get/Set the cache file to ../app/cache/my-cache.html
$content = $cache->start("my-cache.html");
// If $content is null then the content will be generated for the cache
if ($content === null) {
// Print date and time
echo date("r");
// Generate a link to the sign-up action
echo Tag::linkTo(
[
"user/signup",
"Sign Up",
"class" => "signup-button",
]
);
// Store the output into the cache file
$cache->save();
} else {
// Echo the cached output
echo $content;
}
~~~
*溫馨提示*在上面的實例中,我們的代碼維持不變,即輸出給用戶的內容和之前展示的內容是一樣的。我們的緩存組件 以透明的方式捕獲了頁面輸出并保存在緩存文件(當緩存生成時)或者在早期的一次調用時將它發送回用戶預編譯,故而可以避免高昂的操作。
## 緩存任意數據(Caching Arbitrary Data)
僅僅是緩存數據,對于你的應用來說也是同等重要的。緩存通過重用常用的(非更新的)數據可以減少數據庫的加載, 從而加速你的應用。
### 文件后端存儲器例子(File Backend Example)
其中一個緩存適配器是文件’File’。文件適配器的配置中只需要一個key:指明緩存文件存放的目錄位置。 這個配置通過cacheDir選項控制,必須,且要以反斜杠結尾。
~~~
<?php
use Phalcon\Cache\Backend\File as BackFile;
use Phalcon\Cache\Frontend\Data as FrontData;
// Cache the files for 2 days using a Data frontend
$frontCache = new FrontData(
[
"lifetime" => 172800,
]
);
// Create the component that will cache "Data" to a "File" backend
// Set the cache file directory - important to keep the "/" at the end of
// the value for the folder
$cache = new BackFile(
$frontCache,
[
"cacheDir" => "../app/cache/",
]
);
$cacheKey = "robots_order_id.cache";
// Try to get cached records
$robots = $cache->get($cacheKey);
if ($robots === null) {
// $robots is null because of cache expiration or data does not exist
// Make the database call and populate the variable
$robots = Robots::find(
[
"order" => "id",
]
);
// Store it in the cache
$cache->save($cacheKey, $robots);
}
// Use $robots :)
foreach ($robots as $robot) {
echo $robot->name, "\n";
}
~~~
### Memcached 后端存儲器例子(Memcached Backend Example)
當我們改用Memcached作為后端存儲器時,上面的實例改動很輕微(特別就配置而言)。
~~~
<?php
use Phalcon\Cache\Frontend\Data as FrontData;
use Phalcon\Cache\Backend\Libmemcached as BackMemCached;
// Cache data for one hour
$frontCache = new FrontData(
[
"lifetime" => 3600,
]
);
// Create the component that will cache "Data" to a "Memcached" backend
// Memcached connection settings
$cache = new BackMemCached(
$frontCache,
[
"servers" => [
[
"host" => "127.0.0.1",
"port" => "11211",
"weight" => "1",
]
]
]
);
$cacheKey = "robots_order_id.cache";
// Try to get cached records
$robots = $cache->get($cacheKey);
if ($robots === null) {
// $robots is null because of cache expiration or data does not exist
// Make the database call and populate the variable
$robots = Robots::find(
[
"order" => "id",
]
);
// Store it in the cache
$cache->save($cacheKey, $robots);
}
// Use $robots :)
foreach ($robots as $robot) {
echo $robot->name, "\n";
}
~~~
## 查詢緩存(Querying the cache)
添加到緩存的元素根據唯一的key進行識別區分。這使用文件緩存作為后端時,key就是實際的文件名。 為了從緩存中獲得數據,我們僅僅需要通過唯一的key調用即可。如果key不存在,get方法將會返回null。
~~~
<?php
// Retrieve products by key "myProducts"
$products = $cache->get("myProducts");
~~~
如果你想知道在緩存中存放了哪些key,你可以調用queryKeys方法:
~~~
<?php
// Query all keys used in the cache
$keys = $cache->queryKeys();
foreach ($keys as $key) {
$data = $cache->get($key);
echo "Key=", $key, " Data=", $data;
}
// Query keys in the cache that begins with "my-prefix"
$keys = $cache->queryKeys("my-prefix");
~~~
## 刪除緩存數據(Deleting data from the cache)
有些時機你需要強制廢除一個緩存的實體(如對被緩存的數據進行了更新)。 而僅僅需要做的只是知道對應緩存的數據存放于哪個key即可。
~~~
<?php
// Delete an item with a specific key
$cache->delete("someKey");
$keys = $cache->queryKeys();
// Delete all items from the cache
foreach ($keys as $key) {
$cache->delete($key);
}
~~~
## 檢查緩存是否存在(Checking cache existence)
也有可能需要根據一個給定的key來判斷緩存是否存在:
~~~
<?php
if ($cache->exists("someKey")) {
echo $cache->get("someKey");
} else {
echo "Cache does not exists!";
}
~~~
## 有效期(Lifetime)
“有效期”是指緩存可以多久時間(在以秒為單位)內有效。默認情況下,全部被創建的緩存都使用前端構建中設定的有效期。 你可以在創建時指定一個有效期或者在從緩存中獲取數據時:
Setting the lifetime when retrieving:
~~~
<?php
$cacheKey = "my.cache";
// Setting the cache when getting a result
$robots = $cache->get($cacheKey, 3600);
if ($robots === null) {
$robots = "some robots";
// Store it in the cache
$cache->save($cacheKey, $robots);
}
~~~
在保存時設置有效期:
~~~
<?php
$cacheKey = "my.cache";
$robots = $cache->get($cacheKey);
if ($robots === null) {
$robots = "some robots";
// Setting the cache when saving data
$cache->save($cacheKey, $robots, 3600);
}
~~~
## 多級緩存(Multi-Level Cache)
緩存組件的特點,就是允許開發人員使用多級緩存。這個新特性非常有用, 因為你可以在多個緩存媒介結合不同的有效期中保存相同的數據,并在有效期內從首個最快的緩存適配器開始讀取,直至到最慢的適配器。
~~~
<?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,
]
);
// Backends are registered from the fastest to the slower
$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/",
]
),
]
);
// Save, saves in every backend
$cache->save("my-key", $data);
~~~
## 前端適配器(Frontend Adapters)
作為緩存的接口或者輸入源的前端適配器有:
| 適配器 | 描述 |
| --- | --- |
| [Phalcon\\Cache\\Frontend\\Output](http://docs.iphalcon.cn/api/Phalcon_Cache_Frontend_Output.html) | 從標準PHP輸出讀取輸入數據 |
| [Phalcon\\Cache\\Frontend\\Data](http://docs.iphalcon.cn/api/Phalcon_Cache_Frontend_Data.html) | 可用于緩存任何類型的PHP數據(大數組,對象,文本等)。在存入后端前數據將會被序列化。 |
| [Phalcon\\Cache\\Frontend\\Base64](http://docs.iphalcon.cn/api/Phalcon_Cache_Frontend_Base64.html) | 可用于緩存二進制數據。在存入后端前數據會以base64\_encode編碼進行序列化。 |
| [Phalcon\\Cache\\Frontend\\Json](http://docs.iphalcon.cn/api/Phalcon_Cache_Frontend_Json.html) | 在存入后端前數據使用JSON編碼。從緩存獲取后進行JSON解碼。此前端適配器可用于跨語言和跨框架共享數據。 |
| [Phalcon\\Cache\\Frontend\\Igbinary](http://docs.iphalcon.cn/api/Phalcon_Cache_Frontend_Igbinary.html) | 用于緩存任何類型的PHP數據(大數組,對象,文本等)。在存入后端前數據會使用IgBinary進行序列化。 |
| [Phalcon\\Cache\\Frontend\\None](http://docs.iphalcon.cn/api/Phalcon_Cache_Frontend_None.html) | 用于緩存任何類型的PHP數據而不作任何序列化操作。 |
### 自定義前端適配器(Implementing your own Frontend adapters)
為了創建你自己的前端適配器或者擴展已有的適配器,你必須 實現[Phalcon\\Cache\\FrontendInterface](http://docs.iphalcon.cn/api/Phalcon_Cache_FrontendInterface.html)接口。
## 后端適配器(Backend Adapters)
用于存放緩存數據的后端適配器有:
| 適配器 | 描述 | 信息 | 需要的擴展 |
| --- | --- | --- | --- |
| [Phalcon\\Cache\\Backend\\File](http://docs.iphalcon.cn/api/Phalcon_Cache_Backend_File.html) | 在本地絕對路徑的文件上存放數據 | ? | ? |
| [Phalcon\\Cache\\Backend\\Memcache](http://docs.iphalcon.cn/api/Phalcon_Cache_Backend_Memcache.html) | 在memcached服務器存放數據 | [Memcached](http://www.php.net/memcache) | [memcache](http://pecl.php.net/package/memcache) |
| [Phalcon\\Cache\\Backend\\Apc](http://docs.iphalcon.cn/api/Phalcon_Cache_Backend_Apc.html) | 在opcode緩存 (APC)中存放數據 | [APC](http://php.net/apc) | [APC extension](http://pecl.php.net/package/APC) |
| [Phalcon\\Cache\\Backend\\Mongo](http://docs.iphalcon.cn/api/Phalcon_Cache_Backend_Mongo.html) | 在Mongo數據庫中存放數據 | [MongoDb](http://mongodb.org/) | [Mongo](http://pecl.php.net/package/mongo) |
| [Phalcon\\Cache\\Backend\\Xcache](http://docs.iphalcon.cn/api/Phalcon_Cache_Backend_Xcache.html) | 在XCache中存放數據 | [XCache](http://xcache.lighttpd.net/) | [xcache extension](http://pecl.php.net/package/xcache) |
| [Phalcon\\Cache\\Backend\\Redis](http://docs.iphalcon.cn/api/Phalcon_Cache_Backend_Redis.html) | Stores data in Redis | [Redis](http://redis.io/) | [redis extension](http://pecl.php.net/package/redis) |
### 自定義后端適配器(Implementing your own Backend adapters)
為了創建你自己的后端適配器或者擴展已有的后端適配器,你必須 實現[Phalcon\\Cache\\BackendInterface](http://docs.iphalcon.cn/api/Phalcon_Cache_BackendInterface.html)接口。
### 文件后端存儲器選項(File Backend Options)
此后端存儲器把緩存內容存放到本地服務器的文件。對應的選項有:
| 選項 | 描述 |
| --- | --- |
| prefix | 自動追加到緩存key前面的前綴 |
| cacheDir | 放置緩存文件且可寫入的目錄 |
### Memcached 后端存儲器選項(Memcached Backend Options)
此后端存儲器將緩存的內容存放在memcached服務器。對應的選項有:
| 選項 | 描述 |
| --- | --- |
| prefix | 自動追加到緩存key前面的前綴 |
| host | memcached 域名 |
| port | memcached 端口 |
| persistent | 創建一個長連接的memcached連接? |
### APC 后端存儲器選項(APC Backend Options)
此后端存儲器將緩存內容存放到opcode緩存(APC)。對應的選項有:
| 選項 | 描述 |
| --- | --- |
| prefix | 自動追加到緩存key前面的前綴 |
### Mongo 后端存儲器選項(Mongo Backend Options)
此后端存儲器將緩存內容存放到MongoDB服務器。對應的選項有:
| 選項 | 描述 |
| --- | --- |
| prefix | 自動追加到緩存key前面的前綴 |
| server | MongoDB的連接串 |
| db | Mongo數據庫名 |
| collection | Mongo數據庫連接 |
### XCache 后端存儲器選項(XCache Backend Options)
此后端存儲器將緩存內容存放到XCache ([XCache](http://xcache.lighttpd.net/))。對應的選項有:
| 選項 | 描述 |
| --- | --- |
| prefix | 自動追加到緩存key前面的前綴 |
### Redis Backend Options
This backend will store cached content on a Redis server ([Redis](http://redis.io/)). The available options for this backend are:
| Option | Description |
| --- | --- |
| prefix | A prefix that is automatically prepended to the cache keys |
| host | Redis host |
| port | Redis port |
| auth | Password to authenticate to a password-protected Redis server |
| persistent | Create a persistent connection to Redis |
| index | The index of the Redis database to use |
在[Phalcon Incubator](https://github.com/phalcon/incubator)上還有更多針對這個組件可用的適配器
- 簡介
- 安裝
- 安裝(installlation)
- XAMPP下的安裝
- WAMP下安裝
- Nginx安裝說明
- Apache安裝說明
- Cherokee 安裝說明
- 使用 PHP 內置 web 服務器
- Phalcon 開發工具
- Linux 系統下使用 Phalcon 開發工具
- Mac OS X 系統下使用 Phalcon 開發工具
- Windows 系統下使用 Phalcon 開發工具
- 教程
- 教程 1:讓我們通過例子來學習
- 教程 2:INVO簡介
- 教程 3: 保護INVO
- 教程4: 使用CRUD
- 教程5: 定制INVO
- 教程 6: V?kuró
- 教程 7:創建簡單的 REST API
- 組件
- 依賴注入與服務定位器
- MVC架構
- 使用控制器
- 使用模型
- 模型關系
- 事件與事件管理器
- Behaviors
- 模型元數據
- 事務管理
- 驗證數據完整性
- Workingwith Models
- Phalcon查詢語言
- 緩存對象關系映射
- 對象文檔映射 ODM
- 使用視圖
- 視圖助手
- 資源文件管理
- Volt 模版引擎
- MVC 應用
- 路由
- 調度控制器
- Micro Applications
- 使用命名空間
- 事件管理器
- Request Environmen
- 返回響應
- Cookie 管理
- 生成 URL 和 路徑
- 閃存消息
- 使用 Session 存儲數據
- 過濾與清理
- 上下文編碼
- 驗證Validation
- 表單_Forms
- 讀取配置
- 分頁 Pagination
- 使用緩存提高性能
- 安全
- 加密與解密 Encryption/Decryption
- 訪問控制列表
- 多語言支持
- 類加載器 Class Autoloader
- 日志記錄_Logging
- 注釋解析器 Annotations Parser
- 命令行應用 Command Line Applications
- Images
- 隊列 Queueing
- 數據庫抽象層
- 國際化
- 數據庫遷移
- 調試應用程序
- 單元測試
- 進階技巧與延伸閱讀
- 提高性能:下一步該做什么?
- Dependency Injection Explained
- Understanding How Phalcon Applications Work
- Api
- Abstract class Phalcon\Acl