#9 Phpのsession Storeをredisにする

こんにちわ。れいです。

今日はphpのsession storeをredisにしてみようと思います。

負荷分散するときに、セッション、どうしてますか?
keepalivedやapacheのmod_proxy_balancerを使ってバランシングする時に、
バックエンドのAPサーバでセッションを管理していると、困りますよね。

従来は、DBやnfsやmemcachedやrepcachedに入れる方法が主流でしたね。
でも、ちょっと遅かったり再起動をしたら消えてしまったり負荷が心配だったり…
といくつか問題があったようにも思います。

そこで、最近流行りのKVSにphpのセッションを入れて
管理する方法を紹介します。
今回使うのはRedisです。
色んなKVSの中でかなり早い部類に入るのと、
レプリケーションを組むのが非常に簡単であること、
あと僕が使ったことがあるKVSがMongoDBとRedisしかないので、
なんとなく選びました。
(余談ですが、TopotalではRedisを使っています)

phpとRedisのインストールは、もっと詳細に紹介している他サイトさんがあると思うので、
そこに任せます。
(需要があったら書きます)

phpとredisはインストール済みとして話を進めます。
まず、phpでredisを使うために、
phpredisを入れます。
→phpredis( http://github.com/owlient/phpredis )

多分phpizeが要ります。

1
2
3
4
# git clone https://github.com/owlient/phpredis.git
# cd phpredis
# phpize
# ./configure

僕はphpをソースからインストールしていたので、
php-configがどこにあるか指定しろのエラーが出ました。
ので、以下のようにしました。

1
2
3
# ./configure --with-php-config=/usr/local/php/bin/php-config
# make
# make install

これで終わりです。
php-fpmを使っていたのでrestartしておきました。
apacheを使っている人はapacheをrestartしておくと、
よいかもしれません。

phpとredisが正常に連携できているか調べるために、
こんな感じのことをしました。
[php]php -r ‘ $redis = new Redis();
$redis->connect(“127.0.0.1″,6379);
$redis->set(“redis-test”,”test”);
echo $redis->get(“redis-test”); ‘[/php]
これで、test と表示されればOKです。
(redisが127.0.0.1:6379で待ち受けていることが必要です。)

次に、php.iniの設定をします。
普通は/etc/php.iniとかに入ってるような気がします。

1
# vim /usr/local/php/lib/php.ini
1
extension=redis.so

の記述があることを確認します。無ければ追記します。
(ないと多分phpとredisの連携テストでこけますが…)

次に、session.save_handlerを以下のように変更します。

1
session.save_handler = redis

そして、session.save_pathを例えばこんな感じに書きます。

1
session.save_path = "tcp://127.0.0.1:6379?weight=1"

基本的な記法は、

1
tcp://${HOST_ADDRESS}:${HOST_PORT}?${OPTION1}&${OPTION2}...

のような感じです。

使えるオプションは、

1
2
3
4
5
weight
timeout
persistent
prefix
auth

にだと思います。
・weight
weight=INT で指定して、複数のサーバにバランシングすることが出来るみたいです。
デフォルト値は1になってます。
・timeout
timeout=FLOAT で指定して、redisサーバとのタイムアウト値を設定します。
デフォルト値は86400と長いです。
・persistent
0か1を指定出来ます、が、ちょっとちゃんと動いてるか検証出来なかった上に、
公式で実験的な設定というふうな記述があるので、今は触らないほうがいいでしょう。
・prefix
prefix=STRINGで指定して、redisにsessionを格納する際のkey値を指定できます。
デフォルトは”PHPREDIS_SESSION:”になってます。
・auth
redis-serverでAUTHが設定されてる時に設定します。
デフォルトは設定されてません。

3つのサーバにsessionをバランシングしたい時は、次のように書くのがいいでしょう。

1
session.save_path = "tcp://10.0.0.1:6379?weight=1&timeout=3.0,tcp://10.0.0.2:6379?weight=2&timeout=3.0,tcp://10.0.0.3:6379?weight=2&timeout=3.0"

こーんなテストページを作って、実際にSESSIONが入ってるか見てみましょう。

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
session_start();
if (isset( $_SESSION["count"] )) {
  $_SESSION["count"]++;
}else{
  $_SESSION["count"] = 1;
}
?>;




<?php echo htmlspecialchars($_SESSION["count"]) ?>

redis-cliに入って、monitorコマンドを実行して、ページにアクセスしてみましょう。

1
2
3
4
[root@coco-01 ~]# redis-cli 
redis 127.0.0.1:6379>; monitor
OK
"monitor"

作ったテストページに実際にアクセスしてみると、こんな感じになります。

1
2
"GET" "PHPREDIS_SESSION:~~~~~"
"SETEX" "PHPREDIS_SESSION:~~~~~" "1440" "count|i:2;"

どうですか?ちゃんとredisにセッションは入ったでしょうか?

ここに書いたことは、実は大体このページを見れば分かることです。↓
https://github.com/nicolasff/phpredis

それではみなさん愉快なセッションライフを!
(記事の中に間違いとかがあったら、どんどん指摘してくださいね!)