Do You PHP?    
Search Engine Optimization  php5 powerd  Valid XHTML 1.0!  Valid CSS!  このサイトのはてなブックマーク数 



last updated
2005/04/17

counter hits
since 1999/11/06


Turck MMCacheを導入してみる - 実運用での備忘録

cautionITProのPHPウォッチによるとプロジェクトは停止状態にあり、新プロジェクトとしてeAcceleratorプロジェクトが開始されています。近いうちにまた調べてみようと思います。

個人的には評価が非常に高いTurck MMCacheですが、実運用となると意外なところに落とし穴があったりいくつかTips的なものがでてきました。ということで、ここら辺で一度まとめてみました。今回は取りあえず2つほどご紹介します。

データキャッシュのグルーピング機能がない

まず、「データキャッシュのグルーピング機能がない」ため、キャッシュをクリアする場合必ず全てのキャッシュをクリアしなければならないということが挙げられます。PEAR::Cache_Liteにはグルーピング機能があり非常に便利なのですが、MMCacheについては別途実装する必要があります。

具体的には、以下のようなクラス(あるいは関数)を使って、キャッシュキーを管理する事になると思います(ちょっと手抜きです)。

●CacheManager.class.php

<?php
/**
 * データキャッシュ管理クラス
 *
 * @author SHIMOOKA Hideyuki <shimooka@doyouphp.jp>
 * @create 2005/04/17
 * @version $Id$
 * @copyright (C)2005 Hideyuki Shimooka. All rights reserved.
 */
?>
<?php
class CacheManager
{
    var $key_;
    var $group_;

    /**
     * コンストラクタ
     *
     * @param キー
     * @param グループ
     */
    function CacheManager($key, $group = 'default') {
        $this->key_ = $key;
        $this->group_ = $group;
    }

    /**
     * データをキャッシュする
     *
     * @param データ
     * @param 有効期間(秒)。デフォルトは0(無期限)
     */
    function put($value, $ttl = 0)
    {
        $group = mmcache_get($this->getGroup());
        if (is_null($group)) {
            $group = array();
        }
        $group[$this->getkey()] = 1;
        mmcache_lock($this->getGroup());
        mmcache_put($this->getGroup(), $group);
        mmcache_unlock($this->getGroup());

        mmcache_lock($this->getKey());
        mmcache_put($this->getKey(), $value, $ttl);
        mmcache_unlock($this->getKey());
    }

    /**
     * キャッシュされたデータを取得する
     *
     * @return キャッシュされたデータ
     */
    function get()
    {
        return mmcache_get($this->getKey());
    }

    /**
     * キャッシュキーを取得する
     *
     * @return キャッシュキー
     */
    function getKey()
    {
        return $this->key_;
    }

    /**
     * キャッシュグループを取得する
     *
     * @return キャッシュグループ
     */
    function getGroup()
    {
        return $this->group_;
    }

}
?>

これを使った簡単なサンプルは以下の通りです。

●grouping.php

<?php
require_once 'CacheManager.class.php';
?>
<?php
    $cache = new CacheManager('test_key', 'group1');
    $cache->put('ほげほげ');

    var_dump(mmcache_get('group1'));
?>

●grouping.phpの実行結果
array
  'test_key' => 1

キャッシュキーとしてグループ名を指定すると、そのグループに属しているキーを配列として取得することができます。ここまでできると、mmcache_rm関数を使ってグループ単位で削除することも可能になります。

●grouping.php

<?php
require_once 'CacheManager.class.php';
?>
<?php
    $cache = new CacheManager('test_key', 'group1');
    $cache->put('ほげほげ');

    var_dump(mmcache_get('group1'));

    /**
     * 「group1」に属するキャッシュをクリアする
     */
    foreach (mmcache_get('group1') as $key => $value) {
        mmcache_rm($key);
    }
?>

内部的なキャッシュキー

次に最近ちょっとはまったことですが、「キャッシュキーは内部的にアクセス時のドメイン/ホスト名が含まれる」ということが挙げられます。

例えば、

  • 内部IPアドレス:192.168.0.1
  • 外部IPアドレス:xxx.yyy.zzz.123
  • ホスト名:hoge
  • ドメイン名:example.com

というホストがあった場合、アクセス可能なURLは

  • http://192.168.0.1/
  • http://xxx.yyy.zzz.123/
  • http://hoge/
  • http://example.com/

といった具合になると思います。ここで、キャッシュキー「abc123xyz」を考えた場合、各URLでアクセスした場合で異なるキャッシュとして登録されてしまいます。これは、MMCache内部で「ホスト/ドメイン名+:+キャッシュキー」としてキャッシュキーが管理されているためで、具体的なキーはそれぞれ

  • 192.168.0.1:abc123xyz
  • xxx.yyy.zzz.123:abc123xyz
  • hoge:abc123xyz
  • example.com:abc123xyz

という感じになります。VirtualHost等で複数のサイトを運営しているような場合だと、他のサイトに漏洩するとか影響を与えることがない、という意味で正しい実装なのだと思いますが、Firewallやロードバランサが外側にありWWWサーバが複数ある環境でキャッシュを部分的にクリアしたいような場合、結構やっかいな問題になります。

回避策としては、

  • キャッシュされるURL(サービス系)と同じ側からアクセスする
  • Firewall・ロードバランサでポートマッピングを行って、各WWWサーバにアクセスできるようにする(当然、別途アクセス制限は必要)

などが考えられます。後者はMMCacheの内部キーにはポート番号は含まれてないことを利用したものです(同じmmcache.phpなページををhttpとhttpsでアクセスすると分かると思います)。

今回はこんなところで。。。(^-^;



About This Site |  Privacy Policy |  Contact
Copyright © 1999 - 2005 by Hideyuki SHIMOOKA all rights reserved.