phpのセッションをファイルにためる場合はディレクトリを分散させる話

ちょっと大き目のWebサイト=Web/APサーバが複数台あることが前提=をPHPで構築する場合、セッション情報を格納するストレージをどこにするか、という話。

まずはストレージの選択から。

●NFS
実装が一番楽で、 PHP側では特別設定不要。 お手軽さではNo.1だろう。 しかし、過去の経験では一番ナシの方法だ。

問題になるのはガベージコレクション。 セッションの仕組みからしてファイルの作成が大量発生する。 ファイルが溜まりすぎるとlsがなかなか返ってこなくなることがあると思うが、 それがネットワーク越しに発生する。 その間で待ちが発生して結果サーバを止めてしまうことになる。 つまりアクセス集中に極端に弱いのだ。

PHPのセッションを考える - ぎじゅっやさんより。

そうかなあ。。。PHPがセッションをファイルに格納するときの設定パラメータにはこんなのもあるのだが。

session.save_path string
session.save_path は、保存ハンドラに渡される 引数を定義します。デフォルトのファイルハンドラを選択した場合、 ファイルが作成される場所のパスになります。 session_save_path() も参照ください。

オプションの引数としてN(数値)を指定できます。 これはセッションファイルを分散して保存する際に ディレクトリ階層レベルを決定します。 例えば、'5;/tmp'とすると /tmp/4/b/1/e/3/sess_4b1e384ad74619bd212e236e52a5a174If という位置にセッションファイルを生成します。

PHP: セッション - Manual より

ということで、「ひとつのディレクトリの配下にたくさんのファイルを生成するとI/O性能が突然劣化してしまった」という現象を避けるための機能は、PHPのセッション維持機構には、ちゃんとある。NFSに書き込むのか自サーバのローカルディスクに書き込むのかによらずよくある話でよくある対策。

古いセッション情報の削除=セッション格納ファイルの削除=については、ディレクトリ分散させた場合には自動削除処理(ガーベッジコレクションと言うらしい。JavaのJVMのそれとは全く違う話だけど)がなされないので、自分でcronかなにかでやる必要がある。

が、それも簡単で、例えばNFS上の/nfsdir/phpsess/0, /nfsdir/phpsess/1, /nfsdir/phpsess/2....みたいなところに格納されていると仮定して
find /nfsdir/phpsess -type f -mtime +1 -name 'sess_*' | xargs -r rm
といった1行コマンドを1日1回で流しておくだけ。

なお、PHPのセッション機構が云々というよりは、NFSという技術そのものの信頼性がまずビミョーなんだという話もあることはある。(だからNFSに高信頼性を求めると高価になりがちなんだよなー。)

そもそもサーバー間でセッション共有させるのをあきらめてリバースプロキシでサーバー振り分けさせて逃げようとかいろいろな話をもちだすとキリが無いのでこのへんで。

see also:

トラックバックURL

このエントリーのトラックバックURL:
http://www.ywcafe.net/mt/mt-tb.cgi/798

コメントする

(初めてのコメントの時は、コメントが表示されるためにこのブログのオーナーの承認が必要になることがあります。承認されるまでコメントは表示されませんのでしばらくお待ちください)


画像の中に見える文字を入力してください。