|
[2005/02/11] ITProのPHPウォッチによるとプロジェクトは停止状態にあり、新プロジェクトとしてeAcceleratorプロジェクトが開始されています。近いうちにまた調べてみようと思います。
ここ最近紹介してきたTurck MMCacheですが、今回はTurck MMCache APIと呼ばれる拡張関数を試してみました。目的は「データのキャッシュ」です。
MMCacheをインストールすると以下の拡張関数が利用できるようになります(バージョン2.4.6で確認)。これらのうち、mmcache_put関数はPHP変数を保存する事ができ、キャッシュした値はmmcache_get関数で取得することができます。これらをうまく使うとサーバ全体でデータのキャッシュを行うことが可能です。
- mmcache
- mmcache_cache_output
- mmcache_cache_page
- mmcache_cache_result
- mmcache_encode
- mmcache_gc
-
mmcache_get
- mmcache_load
- mmcache_lock
-
mmcache_put
- mmcache_rm
- mmcache_rm_page
- mmcache_set_session_handlers
- mmcache_unlock
以下はキャッシュデータを作成するスクリプトで、Oracleのdept表から全データを取得し連想配列のままキャッシュさせる、というものです。
●setup.php
<?php
$conn = OCILogon("scott", "tiger", "orcl");
$stmt = OCIParse($conn,"SELECT * FROM dept ");
OCIExecute($stmt);
$ret = array();
$record = array();
while (OCIFetchInto($stmt, $record, OCI_ASSOC + OCI_RETURN_NULLS)) {
$ret[] = $record;
}
OCIFreeStatement($stmt);
OCILogoff($conn);
mmcache_lock('dept');
mmcache_put('dept', $ret);
mmcache_unlock('dept');
?>
dept表のデータをメモリに書き込みました。
扱い方としてはファイルの場合と似ており、
というありがちな手続きになります。ただし、データに対する名前(キー)を指定する必要があります。この名前は後ほどキャッシュデータを取得する際に必要になります。
一方の読み込み側ですが、以下のようにmmcache_get関数を使用するだけです。存在しない名前を指定した場合はnullが返りますので、エラー判定などに利用できると思います。
●test.php
<?php
$dept = mmcache_get('dept');
var_dump($dept);
?>
上記を踏まえ以下のようなキャッシュ管理クラスを作ってみました。元ネタはPHP4でデザインパターン(番外編:Intercepting Filterパターン)で作成したFilterManagerクラスです。キャッシュするデータとしては文字列・配列・オブジェクトで、それぞれ別のFilter(CacheBuilder)として定義してあります。
●setup.php
<?php
require_once('jp/ne/hi_ho/pat/dimension/Abstract.phl');
?>
<?php
class CacheBuilder
{
function build() { Abstract::set('build'); }
function getName() { Abstract::set('getName'); }
}
class CacheManager
{
var $chain_;
function CacheManager()
{
$this->chain_ = new CacheBuilderChain();
}
function addCacheBuilder($builders)
{
if (!is_array($builders)) {
$builders = array($builders);
}
foreach ($builders as $idx => $builder) {
$this->chain_->addCacheBuilder($builder);
}
}
function process()
{
$this->chain_->build();
}
function get($name)
{
$data = mmcache_get(strtolower($name));
return $data;
}
}
class CacheBuilderChain
{
var $next_;
function CacheBuilderChain()
{
$this->next_ = array();
}
function addCacheBuilder($next){
array_push($this->next_, $next);
}
function build()
{
reset($this->next_);
foreach ($this->next_ as $idx => $obj) {
$data = $obj->build();
if ($data) {
$name = strtolower($obj->getName());
mmcache_lock($name);
mmcache_put($name, $data);
mmcache_unlock($name);
}
}
}
}
class StringCacheBuilder extends CacheBuilder
{
function build()
{
return 'Copyright © 2004 Hideyuki Shimooka. All rights reserved.';
}
function getName() { return 'string'; }
}
class ArrayCacheBuilder extends CacheBuilder
{
function build()
{
$ret = array();
$ret[] = '最初のデータです';
$ret[] = '2番目データです';
$ret[] = '3番目のデータです';
return $ret;
}
function getName() { return 'array'; }
}
class ObjectCacheBuilder extends CacheBuilder
{
function build()
{
$obj = new stdclass();
$obj->x1 = 10;
$obj->y1 = 15;
$obj->x2 = 20;
$obj->y3 = 25;
return $obj;
}
function getName() { return 'object'; }
}
class DBCacheBuilder extends CacheBuilder
{
function build()
{
$conn = OCILogon('scott', 'tiger', 'orcl');
$stmt = OCIParse($conn,'SELECT * FROM dept ');
OCIExecute($stmt);
$ret = array();
$record = array();
while (OCIFetchInto($stmt, $record)) {
$ret[] = $record;
}
OCIFreeStatement($stmt);
OCILogoff($conn);
return $ret;
}
function getName() { return 'db'; }
}
?>
<?php
$manager = new CacheManager();
$manager->addCacheBuilder(new StringCacheBuilder());
$builders = array(new ArrayCacheBuilder(),
new ObjectCacheBuilder());
$manager->addCacheBuilder($builders);
$manager->process();
echo 'setup successful';
?>
<hr>
<?php
show_source($_SERVER['SCRIPT_FILENAME']);
?>
キャッシュしたデータの取得は、以下のようにCacheManagerクラスのgetメソッドを使用します。setup.phpにアクセスしたPCとは別のPCからアクセスしてみたりすると良いかも知れません。
●main.php
<?php
require_once('CacheManager.phl');
?>
<?php
$manager = new CacheManager();
var_dump($manager->get('string'));
var_dump($manager->get('ARRAY'));
var_dump($manager->get('Object'));
?>
<hr>
<?php
show_source($_SERVER['SCRIPT_FILENAME']);
?>
キャッシュされたデータですが、設定によってはApacheの再起動を行うと消えてしまいます。具体的には、php.iniで
●php.inimmcache.keys="shm_only"
とした場合です。デフォルト値は
●php.inimmcache.keys="shm_and_disk"
で、mmcache.cache_dir指定されたディレクトリにも書き込まれます。このため、Apacheの再起動を行ってもキャッシュが消えることはありません。当然、前述のディレクトリ内の「mmcache-user-*」というファイルを削除してしまうと、キャッシュもクリアされます。また、MMCacheの導入ページの最後で紹介したWeb向けAPIで「Clear」ボタンを押下することでキャッシュをクリアする事ができます。
ここまで作ってみて使い道を考えてみると、今回のサンプルは初期化Servlet的(?)なものでしたが、あるタイミングでDBなどに書き出す仕組みを作って、もっと積極的にアクセスや更新が集中するようなデータやオブジェクトを格納しても良いかも知れません。
ここ最近一番のヒットかも知れない > MMCache
|