Zend Framework - Zend_Cache編

HOME | TOP

■ 概要


負荷の大きな処理や時間のかかる演算など、リクエストが来るたびに実行して導き出していては不利な部分が存在します。

ひとたび実行結果を導き出せたら、これを一定期間保持(キャッシュ)して、保持しているキャッシュデータを返し続けるようにすればかなりの負荷軽減になることが予想できます。

これを実現するのがZend_Cacheというわけです。


キャッシュ処理は「フロントエンド」と呼ばれる部分で行われ、
キャッシュデータの保存には「バックエンド」と呼ばれるアダプタが使われます。

「フロントエンド」の中核はCoreであり、他はこれを継承したクラスとなっています。

Core ..基本機能(Zend_Cache_Core)
Output ..出力を横取りするもの(Zend_Cache_Frontend_Output)
Function ..関数コールの結果(Zend_Cache_Frontend_Function)
Class ..オブジェクトや静的メソッドのコール(Zend_Cache_Frontend_Class)
File ..ファイル更新時間(Zend_Cache_Frontend_File)
Page ..ページ全体(Zend_Cache_Frontend_Page)


フロントエンド用のオプション設定として、キャッシュ期間や自動シリアライズ化(文字列データ以外でも文字列化して保存するための仕組み)などが用意されています。



「バックエンド」にはファイル、SQLiteデータベース、メモリがあります。

File ..ファイルに保存(Zend_Cache_Backend_File)
Sqlite ..SQLiteデータベース(Zend_Cache_Backend_Sqlite)
Memcached ..memcachedサーバ(Zend_Cache_Backend_Memcached)


バックエンド用のオプション設定として、キャッシュファイルの保存先ディレクトリ指定などがあります。



キャッシュ処理を行うには、キャッシュ処理を行うフロントエンドをインスタンス化することになります。
そのために静的メソッドfactory()に必要な設定を渡して組み立てます。

以上を踏まえて、実際にフロントエンドのオブジェクトを取得してみます。

上記は基本機能を持つCoreクラスで30秒期限でキャッシュ処理を行い、キャッシュデータ保存を./data内にファイル作成して行うというものです。

実際に./dataディレクトリが存在していないと、「cache_dir must be a directory」の例外をZend_Cache_Exceptionがスローします。
そしてそれをcatchできなければ「Fatal error: Uncaught exception」になります。


■ 使用例


まず「どの処理部分」を「どれくらいの期間」キャッシュさせたいのかをはっきりさせる必要があります。

「処理A」「処理B」「処理C」とあって、そのうちの時間のかかる処理Bがあったとすると処理Bをキャッシュさせることになるので、処理B全体をキャッシュされてるかどうかの判定文で囲むことになります。

これで指定した期間だけ、重い処理をスキップする流れになります。

キャッシュには一意なIDを付けます。他の部分で使われるキャッシュIDとカブらないように、その部分の処理にちなんだIDを付けるのが望ましいです。

一意なIDを付けることで、ファイルやSQLiteデータベースなどに保存したID名義のデータを引っ張り出してくることができます。

では実際のコードを書いてみます。

▼ 重い処理部分をキャッシュする

この結果は、最初にキャッシュが存在しないので

[処理A]重い処理を実行[処理B][処理C]

という表示になり、その後の10秒間は何度アクセスしても

[処理A][処理B][処理C]

と表示されます。

つまり、キャッシュの条件文で囲った範囲の処理が、「実行されては10秒間キャッシュ」を繰り返す流れになります。



次に、echoやprintなどで標準出力される処理をキャプチャします。
これにはフロントエンドにOutputクラスを使用します。

▼ 出力をキャプチャする

今回は出力がキャプチャされるので前回のようにif文内に「echo '重い処理を実行';」と書いてもこれ自体がキャプチャされキャッシュされてしまうのでechoは使わずに変数への代入を行い判別します。

すると最初のアクセスでは以下の表示になり、

[処理A][処理B]if内が実行された[処理C]

次の10秒間は何度アクセスしても以下が表示される流れになります。

[処理A][処理B]if内が実行されてない[処理C]



最後は究極、ページ全体のキャッシュを行ってみます。

これは指定期間キャッシュされたページをそのまま返し続けるので、さながら静的であるHTMLファイルをリクエストしてる形に近くなり、かなりの処理軽減が見込めます。

ページ丸ごとのキャッシュなので、IDは自動的に$_SERVER['REQUEST_URI']に基づいて生成されます。
その他オプションとしてこれに$_GET, $_POST, $_SESSION, $_COOKIE, $_FILESの値を加味したIDを生成することもできます。

▼ ページ全体をキャッシュ

これを実行すると以下の表示になります。

1290744684[処理A][処理B][処理C]

その後2時間は何度リクエストしても以下の表示になります。

DEBUG HEADER : This is a cached page !1290744684[処理A][処理B][処理C]

もしページ全体のキャッシュが効かない場合には、クッキーが送られてる可能性があります。

これを回避するには、cache_with_cookie_variablesキーの値をtrueにしてクッキー値に基づいたIDでキャッシュする方法があります。

フロントエンドのオプション

"regexps"キーの持つ値として、ページごとの設定を配列で追加指定することができます。リクエストURIの正規表現をキーとして、それにマッチしたリクエストに対する挙動を指定することができます。つまりページ単位でキャッシュを違う挙動にできるということになります。

先ほどcache_with_cookie_variablesを設定にした時には、make_id_with_cookie_variablesの値がデフォルトのtrueだったので省略していました。
なので、これをfalse指定にするとクッキー値がなんであろうと関係なくスルーする挙動になります。
つまり$_SERVER['REQUEST_URI']のみでIDが作成されることになります。

フロントエンドのオプション

2010(C)Mingw