Improving Performance with Cache

Phacon提供 Phalcon\Cache 类允许更快地访问常用或已处理的数据。 Phalcon\Cache 是用 C 编写的实现更高的性能和降低开销,当从后端获取项目。 此类使用前端和后端组件的内部的结构。 前端组件作为输入的源或接口后, 端组件提供对类的存储选项。

什么时候使用缓存

Although this component is very fast, implementing it in cases that are not needed could lead to a loss of performance rather than gain. We recommend you check this cases before using a cache:

  • 你使复杂的运算,每次都返回相同的结果 (不经常更改)
  • 你正在使用大量的助手和生成的输出几乎都是一样
  • 你正在不断地访问数据库中的数据,这些数据很少更改

缓存行为

缓存的过程分为 2 个部分:

  • <0Frontend: 这一部分是负责检查,如果密钥已过期,并且执行更多转换对数据存储之前和之后从后端-检索
  • Backend: 这部分是负责沟通,写/读前端所需的数据。

工厂

实例化前端或后端适配器可以通过两种方式实现:

传统的方式

<?php

use Phalcon\Cache\Backend\File as BackFile;
use Phalcon\Cache\Frontend\Data as FrontData;

// Create an Output frontend. Cache the files for 2 days
$frontCache = new FrontData(
    [
        '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/',
    ]
);

或使用工厂对象,如下所示:

<?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 天)。

The implementation of this caching mechanism allows us to gain performance by not executing the helper Phalcon\Tag::linkTo() call whenever this piece of code is called.

<?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 just data is equally important for your application. Caching can reduce database load by reusing commonly used (but not updated) data, thus speeding up your application.

文件后端示例

缓存的适配器之File。 此适配器的唯一的重点区域是位置的将存储缓存文件的位置。 这是由 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 后端。

<?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';
}

查询缓存

The elements added to the cache are uniquely identified by a key. 在文件的后端,关键是实际的文件名。 要从缓存中检索数据,我们只需要调用它使用的唯一键。 如果不存在的键,get 方法将返回 null。

<?php

// Retrieve products by key 'myProducts'
$products = $cache->get('myProducts');

如果你想要知道哪些键存储在缓存中你可以调用 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');

从缓存中删除数据

There are times where you will need to forcibly invalidate a cache entry (due to an update in the cached data). The only requirement is to know the key that the data have been stored with.

<?php

// Delete an item with a specific key
$cache->delete('someKey');

$keys = $cache->queryKeys();

// 从缓存中删除这些数据
foreach ($keys as $key) {
    $cache->delete($key);
}

检查缓存是否存在

它是可能要检查是否缓存中已存在具有给定的键:

<?php

if ($cache->exists('someKey')) {
    echo $cache->get('someKey');
} else {
    echo 'Cache does not exists!';
}

生命周期

A lifetime is a time in seconds that a cache could live without expire. By default, all the created caches use the lifetime set in the frontend creation. 在创建或从缓存中数据的检索,您可以设置特定的生存期:

设置生存期时检索:

<?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);
}

多级缓存

高速缓存组件,此功能允许开发人员来实现多级缓存。 这一新功能是十分有用的因为你可以将相同的数据保存在几个缓存位置具有不同的生存期,首先阅读从一个更快的适配器和结束与最慢的一个,直到数据过期:

<?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);

前端适配器

使用可用的前端适配器接口或输入的源到缓存中:

适配器 描述
Phalcon\Cache\Frontend\Output 从标准的 PHP 输出中读取输入的数据。
Phalcon\Cache\Frontend\Data It's used to cache any kind of PHP data (big arrays, objects, text, etc). Data is serialized before stored in the backend.
Phalcon\Cache\Frontend\Base64 It's used to cache binary data. The data is serialized using base64_encode before be stored in the backend.
Phalcon\Cache\Frontend\Json Data is encoded in JSON before be stored in the backend. Decoded after be retrieved. This frontend is useful to share data with other languages or frameworks.
Phalcon\Cache\Frontend\Igbinary It's used to cache any kind of PHP data (big arrays, objects, text, etc). Data is serialized using Igbinary before be stored in the backend.
Phalcon\Cache\Frontend\None 它用来缓存任何类型的 PHP 数据没有将其序列化。

执行您自己的前端适配器

以创建您自己的前端适配器或扩展现有的必须实现 Phalcon\Cache\FrontendInterface 接口。

后端适配器

后端适配器可用于存储缓存数据如下:

适配器 描述 信息 所需的扩展
Phalcon\Cache\Backend\Apc 存储数据到替代 PHP 缓存 (APC)。 APC APC
Phalcon\Cache\Backend\Apcu 存储数据的处理 (APC 不操作码缓存) APCu APCu
Phalcon\Cache\Backend\File 存储到本地普通文件的数据。
Phalcon\Cache\Backend\Libmemcached 存储到 memcached 服务器数据。 Memcached Memcached
Phalcon\Cache\Backend\Memcache Stores data to a memcached server. Memcache Memcache
Phalcon\Cache\Backend\Mongo Stores data to Mongo Database. MongoDB Mongo
Phalcon\Cache\Backend\Redis 储存数据到Redis. Redis Redis
Phalcon\Cache\Backend\Xcache 在 XCache 中存储数据。 XCache XCache

工厂

有很多 (见 后端适配器) 的后端适配器。 您将取决于您的应用程序的需要使用。 下面的示例加载后端缓存适配器类使用 适配器 选项,如果前端将提供数组作为它将调用前端缓存工厂

<?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 接口。

文件后端选项

This backend will store cached content into files in the local server. The available options for this backend are:

选项 描述
前缀 自动预置到缓存键的前缀。
cacheDir 将缓存的文件可写目录。

Libmemcached 后端选项

This backend will store cached content on a memcached server. Per default persistent memcached connection pools are used. The available options for this backend are:

常规选项

选项 描述
statsKey 用于动态跟踪的缓存键。
prefix 自动预置到缓存键的前缀。
persistent_id 若要创建一个请求之间仍然存在的实例,使用 persistent_id 指定实例的唯一 ID。

服务器选项

选项 描述
host Memcached 主机。
port Memcached 端口。
weight The weight parameter effects the consistent hashing used to determine which server to read/write keys from.

客户端选项

Used for setting Memcached options. See Memcached::setOptions for more.

示例

<?php
use Phalcon\Cache\Backend\Libmemcached;
use Phalcon\Cache\Frontend\Data as FrontData;

// Cache data for 2 days
$frontCache = new FrontData(
    [
        'lifetime' => 172800,
    ]
);

// Create the Cache setting memcached connection options
$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 后端选项

This backend will store cached content on a memcached server. The available options for this backend are:

选项 描述
prefix A prefix that is automatically prepended to the cache keys.
host Memcached 主机。
port Memcached 端口。
persistent 创建到 memcached 的持久性连接吗?

APC Backend Options

This backend will store cached content on Alternative PHP Cache (APC). The available options for this backend are:

选项 描述
prefix 自动预置到缓存键的前缀。

APCU 后端选项

This backend will store cached content on Alternative PHP Cache (APCU). The available options for this backend are:

选项 描述
prefix 自动预置到缓存键的前缀。

Mongo Backend Options

This backend will store cached content on a MongoDB server (MongoDB). The available options for this backend are:

选项 描述
prefix 自动预置到缓存键的前缀。
服务器 MongoDB 的连接字符串。
db 输入数据库名称。
collection Mongo 集合在数据库中。

XCache 后端选项

This backend will store cached content on XCache (XCache). The available options for this backend are:

选项 描述
prefix A prefix that is automatically prepended to the cache keys.

Redis Backend Options

This backend will store cached content on a Redis server (Redis). The available options for this backend are:

选项 描述
prefix A prefix that is automatically prepended to the cache keys.
host Redis的主机。
port Redis的端口
auth 密码保护Redis服务器进行身份验证的密码。
persistent 创建与Redis持久连接。
index Frontend数据库使用的索引。

有更多的适配器可供此 Phalcon incubaror 中的组件