概要
PHPのRedis通信拡張(extension)であるPhpRedisでは、通常のRedisへの入出力に加えて、PHPセッションを保存する機能が提供されています。
PHPセッションは、デフォルトでは/tmpや/var/tmpなどといった一時ディレクトリにファイルとして保存されます。高負荷が予期されるサーバにおいて、ファイルI/Oが気になるような環境では、memcachedやRedisといったオンメモリKVSデータベースの利用を考えることになりますが、PhpRedisはその選択肢の1つになるのではないでしょうか。
インストール
PhpRedisのインストール自体はLinux系ならyumやapt-get、macOSならHomeBrewやMacPorts、*BSD系ならports collectionといった各パッケージシステムから利用できるかと思います。
また、私が書いたこちらも、参考になれば幸いです。
参考:macOS(Mac OS X)にPhpRedisをインストール
設定
PhpRedisのGitHubにあるREADME.markdownに書いてあるとおり、PhpRedisではphp.iniにハンドラ設定をすることでPHPセッションを保存に対応すると記されています。
PHPセッションを保存するには、php.iniに次のような2行を設定します。
# grep ^session /opt/local/etc/php56/php.ini
session.save_handler = redis
session.save_path = "tcp://localhost:6379"
(以下略)
1行目はハンドラとしてredisを使うことを宣言しています。デフォルトではここはfilesになっていますので、ここを書き換えます。
書き換えがためらわれる方は、ここを行コピーして、filesの行をコメントし、コピー行のfilesをredisに書き換えます。
2行目は保存パスです。filesの場合はここは/tmpなどのようにディレクトリパスが記載されていますが、redisではTCP経由で行いますので、tcp://localhost:6379を指定しています。
注意したいのはlocalhostの部分で、ここはredis-serverがコネクションを確立できる(TCP経由でデータを送受信できる)アドレスを指定します。ホスト名もしくはIPアドレスを指定することになります。
ホスト名(IPアドレス)の項目の右にある:の、さらに右にある数値がポート番号で、デフォルトではRedisは6379/TCPを使用します。別のポート番号を使っている人は、ここの値も同じものにしてください。
いくつかオプションが付けられますが、複数サーバでの運用とかタイムアウトとか、そうしたものを指定したい場合に加えることができます(少しだけ後述)。
動作確認
さて、これで本当にRedisに保存されるのでしょうか。
ということで、動作確認をしてみます。redis-serverはあらかじめ起動しておく必要があります。
# redis-server &
次に、PHPセッションを使うテストコードsession.phpを用意します。
<?php
session_start();
echo "save_handler=" . ini_get("session.save_handler") . "\n";
echo "save_path=" . ini_get("session.save_path") . "\n";
echo "session_id=" . session_id() . "\n";
$_SESSION['libname'] = "PhpRedis";
テストコードを実行する前に、必要な確認作業があります。
当然ですが、現時点でRedisに何も(少なくともPHPセッションIDなどが)入っていないことを確認しなければなりません。
> redis-cli
127.0.0.1:6379> keys *
(empty list or set)
この場合は、あらゆるキーが入っていないことを確認できましたので、心置きなく動作確認ができます。
では、さきほどのsession.phpを実行してみましょう。
> php56 session.php
save_handler=redis
save_path=tcp://localhost:6379
session_id=h59pqds8s5sdj9j0anmiqh63s0
save_handlerやsave_pathが、さきほどphp.iniに設定したものと同じになっていれば、設定とテストコードはうまく合致していそうです。
そして、ここが肝心な部分ですが、表示されているsession_idと同じものが、Redisに保存されて入れば、成功ということになります。redis-cliコマンドで確認してみましょう。
> redis-cli
127.0.0.1:6379> keys *
1) "PHPREDIS_SESSION:h59pqds8s5sdj9j0anmiqh63s0"
キーは含まれています。どうやら通信も行われてRedisにキーが保存できているようです。
では、$_SESSION["libname"]に代入した値は保存されているでしょうか。
セッションIDをキーにしてredis-cliからgetしてみましょう。
127.0.0.1:6379> get PHPREDIS_SESSION:h59pqds8s5sdj9j0anmiqh63s0
"libname|s:8:\"PhpRedis\";"
こちらも保存されているようですね。ファイルにPHPセッションを保存しているのと同様に、PHPシリアライズで保存されてます。保存内容自体は、保存先(save_handler)が変わっても同じであることも確認できたと言えそうです(当然ちゃ当然ですけど)。
オプション
最後に、指定できるオプションを簡単にご紹介しておきます。説明自体はPhpRedisのGitHubリポジトリにあるREADME.markdownのPHP Session handlerの項目に書かれています。
オプション | 型 | デフォルト | 意味 |
---|---|---|---|
weight | 整数(integer) | 1 | ホスト(サーバ)の重み付けの値。PHPセッションを複数のRedisホストに分散して保存する場合の比重を設定することができる。あるRedisサーバAが別のRedisサーバBの2倍の重みを持っているとしたら、Aは2倍のセッションを保持することになる。 |
timeout | 小数(float) | 86400 | Redisサーバへのコネクションタイムアウトまでの秒数。この時間以内にRedisサーバに接続できなかった場合、クライアントはセッションを利用できない。 |
persistent | 0もしくは1 | 0 | 永続的コネクションで利用する場合は1を指定する(試験的オプション)。 |
prefix | 文字列 | PHPREDIS_SESSION: | キーの接頭辞として使用する文字。さきほどの動作確認でのキーを見ると、デフォルトの接頭辞が付いているのがわかる。 |
auth | 文字列 | (空欄) | コマンド早出前の認証キー。Redisでauthを使っている場合に使用する。 |
database | 整数 | -1 | データベース番号を指定する。 |
オプションの指定の仕方は、さきほどのREADME.markdownのPHP Session handlerの項目に書かれています(以下抜粋)。
session.save_path = "tcp://host1:6379?weight=1, tcp://host2:6379?weight=2&timeout=2.5, tcp://host3:6379?weight=2"