sessionのガベージコレクションについて[PHP]
これは、sessionが2年間消さない設定にされていたのを、1週間にしたとき気になって調べたことのまとめです。
ざっくり起きた内容まとめ
- RDSの容量が無料枠の20Gを食いつぶそうとしていた
- 原因は過去にsessionデータをdatabaseに保存しているのを知りながら、有効期限を2年にしたから
- 8Gほどに上るデータを削除しなければいけない
まずはCodeIgniterの設定を見てみる
$config['sess_expiration'] = 60*60*24*30*12*2;
( ^ω^ )どうしてこうなったし・・
およそ2年データを保持するという設定が書かれていました。
(なら、DBにわざわざ持たせるなという話ですが・・・)
CodeIgniterのコードを読んでみると、sess_expirationでは後述のmax_lifetimeしか設定できなさそうなので、これを1週間とかにするのはなんだか嫌な予感がすると思い、PHPの挙動を調べてみることにしました。
※実際、30日にしてみると一気にsessionが消えたので、一斉削除する処理が走っていると予想されます。
PHPのリファレンスを見てみる
1.必要な設定情報
注目するべきは以下の項目です。
config名 | デフォルト値 | ドキュメントから抜粋 |
---|---|---|
session.gc_probability | 1 | session.gc_probabilityと session.gc_divisorの組み合わせでgc (ガーベッジコレクション)ルーチンの始動を制御します。 |
session.gc_divisor | 100 | session.gc_divisorと session.gc_probabilityの組み合わせで すべてのセッションの初期化過程でgc(ガーベッジコネクション)プロセス も始動する確率を制御します。 |
session.gc_maxlifetime | 1440 (秒) | session.gc_maxlifetime は、データが 'ごみ' とみなされ、消去されるまでの秒数を指定します。 |
2.挙動
gc_divisorとgc_probabilityの動作が気になったので、さらにPHP知っている人にも聞いてみることにしました。 どうやら、以下の式が成り立つときにgcが実行されるようです。
実際のPHPコードを読んでみましたが、下記の箇所が該当すると思います。
nrand = (zend_long) ((float) PS(gc_divisor) * php_combined_lcg()); if (PS(gc_probability) > 0 && nrand < PS(gc_probability)) { PS(mod)->s_gc(&PS(mod_data), PS(gc_maxlifetime), &num); }
また、gcが動作すると、max_lifetimeを超えているセッションデータは一斉に削除されます。
一斉に削除されます(←ここ重要)
そのため、使用しているDBの性能によっては、動作が重くなる可能性もあるので注意しましょう。
できることなら、ある程度の件数ずつ削除していくといいのではないかと思います。
そろそろPythonのこと書いていきたい・・ Chainerもっと頑張らなきゃ
参考
PHPの公式リファレンス:PHP: 実行時設定 - Manual
PHPのセッションに関するコード:php-src/session.c at master · php/php-src · GitHub