キャッシュによるパフォーマンスの向上

Phalcon は、頻繁に使用される、またはすでに処理されたデータに、高速なアクセスを行う 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:

  • 毎回同じ結果 (変更頻度の低い) を返す複雑な計算をしている
  • 多くのヘルパを利用し、生成される出力がほとんど同じである
  • 常にデータベースのデータにアクセスしており、これらのデータはほとんど変わらない

メモ キャッシュを実装した後でも、一定の期間でキャッシュのヒット率を確認するようにしましょう。 特にMemcacheやApcの場合、バックエンドが提供する関連ツールを使用すると、これを簡単に行うことができます。

キャッシュの振る舞い

キャッシュ処理は、2 つの部分に分かれています。

  • フロントエンド: この部分は、キーが期限切れになっていないかどうかをチェックし、保存する前にデータに追加の変換を実行します。
  • バックエンド: この部分は、フロントエンドが必要とするデータの通信、書き込み、読み取りを行います。

ファクトリー

フロントエンドまたはバックエンドのアダプタをインスタンス化するには、次の2つの方法があります。

従来の方法

<?php

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

// 出力フロントエンドの作成。 ファイルを2日間キャッシュ。
$frontCache = new FrontData(
    [
        'lifetime' => 172800,
    ]
);

// 'Output'から'File'バックエンドにキャッシュするコンポーネントを作成する
// キャッシュファイルディレクトリを設定する - フォルダの値の最後に '/'を置くことが重要
$cache = new BackFile(
    $frontCache,
    [
        'cacheDir' => '../app/cache/',
    ]
);

次のようにFactoryオブジェクトを使用します:

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

use Phalcon\Tag;
use Phalcon\Cache\Backend\File as BackFile;
use Phalcon\Cache\Frontend\Output as FrontOutput;

// 出力フロントエンドの作成。 ファイルを2日間キャッシュ。
$frontCache = new FrontOutput(
    [
        'lifetime' => 172800,
    ]
);

// 'Output'から'File'バックエンドにキャッシュするコンポーネントを作成する
// キャッシュファイルディレクトリを設定する - フォルダの値の最後に '/'を置いておくことが重要です
$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する
    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.

ファイルバックエンドの例

キャッシュのアダプターの1つは、Fileです。 このアダプターの唯一重要なところは、そのキャッシュファイルを保存する場所です。 これは、cacheDir オプションで制御できます。このディレクトリは、最後が バックスラッシュで終らなければなりません。

<?php

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

// Dataフロントエンドを使用して2日間ファイルをキャッシュする
$frontCache = new FrontData(
    [
        'lifetime' => 172800,
    ]
);

// 'Data'を'File'バックエンドにキャッシュするコンポーネントを作成する
// キャッシュファイルディレクトリを設定する - フォルダの値の最後に `/`を置くことが重要
$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

use Phalcon\Cache\Frontend\Data as FrontData;
use Phalcon\Cache\Backend\Libmemcached as BackMemCached;

// データを1時間キャッシュする
$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';
}

注意 save()を呼び、論理値を返します。これは成功 (true) または失敗 (false) を示します。 使用しているバックエンドに応じて、関連するログを調べて障害を特定する必要があります。

キャッシュの確認

このキャッシュに加えられた要素はキーによって一意に特定できます。 ファイルバックエンドの場合、キーは実際のファイル名です。 キャッシュからデータを取得するため、一意のキーを使って呼び出さなければなりません。 もしキーが存在しない場合、getメソッドはnullを返します。

<?php

// キー'myProducts'で製品を取得する
$products = $cache->get('myProducts');

もしあなたがどのようなキーがそのキャッシュに保存されているのかが知りたい場合、queryKeys メソッドを呼びだすことができます。

<?php

// キャッシュで使用されているすべてのキーを照会する
$keys = $cache->queryKeys();

foreach ($keys as $key) {
    $data = $cache->get($key);

    echo 'Key=', $key, ' Data=', $data;
}

// '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

// 対象のキーを持つアイテムを削除する
$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!';
}

有効期間

有効期間は、期限が切れるまでキャッシュが存続できる時間(秒)です。 デフォルトでは、作成されたすべてのキャッシュは、フロントエンドの作成時に設定された有効期間を使用します。 キャッシュからのデータの作成または取得では、特定の有効期間を設定できます。

取得時の有効期間の設定:

<?php

$cacheKey = 'my.cache';

// 結果を取得するときにキャッシュを設定
$robots = $cache->get($cacheKey, 3600);

if ($robots === null) {
    $robots = 'some robots';

    // キャッシュに格納
    $cache->save($cacheKey, $robots);
}

保存時の有効期間の設定:

<?php

$cacheKey = 'my.cache';

$robots = $cache->get($cacheKey);

if ($robots === null) {
    $robots = 'some robots';

    // データを保存するときにキャッシュを設定
    $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,
    ]
);

// バックエンドは、早いものから遅いものへと順番に登録される
$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データをシリアル化せずにキャッシュするために使用されます。

独自フロントエンドアダプターの実装

The Phalcon\Cache\FrontendInterface interface must be implemented in order to create your own frontend adapters or extend the existing ones.

バックエンドアダプター

キャッシュデータを格納するために使用できるバックエンドアダプタは次のとおりです:

アダプター 説明 情報 必須エクステンション
Phalcon\Cache\Backend\Apc Alternative PHP Cache (APC) にデータを格納します。 APC APC
Phalcon\Cache\Backend\Apcu データをAPCuに格納します(オペコードキャッシングなしのAPC) APCu APCu
Phalcon\Cache\Backend\File ローカルのプレーンファイルにデータを格納します。    
Phalcon\Cache\Backend\Libmemcached memcachedサーバーにデータを格納します。 Memcached Memcached
Phalcon\Cache\Backend\Memcache memcachedサーバーにデータを格納します。 Memcache Memcache
Phalcon\Cache\Backend\Memory メモリ中にデータを保存    
Phalcon\Cache\Backend\Mongo データをMongoデータベースに保存します。 MongoDB Mongo
Phalcon\Cache\Backend\Redis Redisにデータを格納します。 Redis Redis
Phalcon\Cache\Backend\Xcache XCacheにデータを格納します。 XCache XCache
注意 PHP7で Phalcon apc ベースのアダプター クラスを使用する場合、pecl から apcuapcu_bc パッケージをインストールする必要があります。 Now in Phalcon 3.4.0 you can switch your <em>\Apc classes to </em>\Apcu and remove apcu_bc. Phalcon 4 では、ほとんどすべての *\Apc クラスを削除したことを覚えていてだください。 {.alert.alert-warning}

ファクトリー

多くのバックエンドアダプタがあります (バックエンドアダプターを参照)。 使用するものはアプリケーションのニーズに応じて異なります。 次の例では、adapterオプションを使用してBackend Cache Adapterクラスをロードし、フロントエンドが配列として提供される場合はFrontend Cache Factoryが呼ばれます。

<?php

use Phalcon\Cache\Backend\Factory;
use Phalcon\Cache\Frontend\Data;

$options = [
    'prefix'   => 'app-data',
    'frontend' => new Data(),
    'adapter'  => 'apc',
];
$backendCache = Factory::load($options);

独自のバックエンドアダプターを実装

The Phalcon\Cache\BackendInterface interface must be implemented in order to create your own backend adapters or extend the existing ones.

ファイルバックエンドのオプション

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

オプション 説明
prefix キャッシュキーの前に自動的に付加される接頭辞。
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 weightパラメータは、キーを読み書きするサーバを決定するために使用されるコンシステントハッシュ法に影響します。

クライアント設定

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

<?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バックエンドのオプション

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

オプション 説明
prefix キャッシュキーの前に自動的に付加される接頭辞。
host Memcachedホスト。
port memcachedポート番号。
persistent memcachedへの永続的な接続を作成するかどうか。

APCバックエンドのオプション

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バックエンドのオプション

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

オプション 説明
prefix キャッシュキーの前に自動的に付加される接頭辞。
server MongoDB接続文字列。
db Mongoデータベース名。
collection データベースのMongoコレクション。

XCacheバックエンドのオプション

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

オプション 説明
prefix キャッシュキーの前に自動的に付加される接頭辞。

Redisバックエンドのオプション

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

オプション 説明
prefix キャッシュキーの前に自動的に付加される接頭辞。
host Redisホスト。
port Redisポート。
auth パスワードで保護されたRedisサーバーに認証するためのパスワード。
persistent Redisへの永続的な接続を作成するかどうか。
index 使用するRedisデータベースのインデックス。

Phalcon Incubator には、このコンポーネントを利用するための複数のアダプターが用意されています。