Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

セッションをメモリに保存する

More than 3 years have passed since last update.

デフォルトではセッションはファイルに書き出されます。
ディスクI/Oはボトルネックなので、より早いメモリ保存にしてみます。

とりあえずWindows版PHP7にはAPCuが入ってないのでPECLから拾ってくる。
今回は1.0.3のDLLをダウンロード。
解凍したらextディレクトリにphp_apcu.dllを置いてphp.iniに以下を記載。
Linuxなら適当にpeclコマンドでも使って。

extension=php_apcu.dll
[APCu]
apc.enabled = 1
apc.entries_hint = 4096
apc.gc_ttl = 3600
apc.ttl = 3600

Apacheを再起動したらAPCu関数が使えるようになっているはず。

class MySessionHandler implements SessionHandlerInterface{

    /**
    * コンストラクタ
    * @param string パス
    * @param string session_name()
    * @return bool true
    */
    public function open($save_path, $name): bool {
        return true;
    }

    /**
    * デストラクタ
    * @return bool true
    */
    public function close(): bool {
        return true;
    }

    /**
    * session_destroy()した
    * @param string session_id()
    * @return bool true
    */
    public function destroy($session_id): bool {
        if(apcu_exists($session_id)){
            return apcu_delete($session_id);
        }
        return true;
    }

    /**
    * $_SESSIONを返す。
    * @param string session_id()
    * @return string session_encode($_SESSION)
    */
    public function read($session_id): string {
        return apcu_fetch($session_id);
    }

    /**
    * $_SESSIONを保存する。
    * @param string session_id()
    * @param string session_encode($_SESSION)
    * @return bool true
    */
    public function write($session_id, $session_data): bool {
        return apcu_store($session_id, $session_data, (int)ini_get('apc.ttl'));
    }

    /**
    * ガベージコレクションが動いた。
    * @param int session.gc_maxlifetime
    * @return bool true
    */
    public function gc($maxlifetime): bool {
        $list = apcu_cache_info();
        $ttl = (int)ini_get('apc.gc_ttl');
        foreach($list['cache_list'] as $v){
            if( ($v['access_time'] + $ttl) < $_SERVER['REQUEST_TIME']){
                apcu_delete($v['info']);
            }
        }
        return true;
    }
}

    // セッションハンドラ変更
    session_set_save_handler(new MySessionHandler(), true);

    // 以後セッションはメモリに保存される
    session_start();
    session_regenerate_id();
    $a=session_id();
    $_SESSION['a'] = 'b';

session_name()とか実装してないけど誰も使わないからいいよね。

gcは不要になったAPCuを削除しています。
apcu_store()は配列に値を入れるようなもので、ttlを越えると配列の値は取得できなくなりますが、配列のキー自体は残っています。
そのためキー自体を削除する処理が入っています。
APCUIteratorでは何故かオプションAPC_LIST_DELETEDを指定しても取得できませんでした。
しかしここはapc.ttlapc.gc_ttlsession.gc_maxlifetimeどれに従うべきなんだろうか。

さて、せっかく作ったはいいけど、大人数が使うサービスでやるとメモリ不足で死ぬし、少人数しかいないサービスではそもそもディスクアクセスでも十分な速度だから作る必要無いしで、需要がよくわからない。

rana_kualu
不労所得で生きたい。
https://twitter.com/rana_kualu
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away