@kyanny's blog

My life. Opinions are my own.

Rails のセッションと MemCache (かきかけ)

Rails でセッションの保存先に :mem_cache_store を指定してる場合に、具体的にどういうキー名で保存されているのか知りたくてソースを読んだ。ついでに memcache-client のソースも読んだ。そのときのメモ。

結論からいうと、 "{namespace}:session:#{session.session_id}" みたいになってる。 namespace は MemCache.new に option で渡したもの。たとえば "app-session-#{RAILS_ENV}" とか。この場合 production 環境であれば最終的に "app-session-production:session:abcabcabcabcabcabcabcabcabcabcabcabc" のようになる。このキーで memcache.get すれば、あるユーザーの Rails のセッションに保存されてるデータをみることができる。 irb からデバッグするときとかに便利、というか毎回このキー名を得るためにいろいろ調べて苦労してたのでいい加減メモを残しておく。

キー名とは別に、「セッションを保存してる memcached ノードが無くなった場合に何がおこるか?」というのも知りたくてやはりソースを読んだ。具体的にどのへんを読んだかメモを残してないので忘れたけど、これは memcache-client のインスタンスが保持してるノードのリストから外した場合と、ノードリストに含まれてるけどサーバがダウンして接続できない場合で違っていて、前者の場合は Rails のコードで空のセッションを作るようになっていたので安全に外すことができる。後者はダメで例外が発生する。なので、 Rails アプリケーションからセッション保存先に指定している memcached ノードを減らす必要がある場合はまず memcache.servers からノードを外すのを先にやること。でないとダウンしたノードにセッションが格納されてる一部のユーザーがぜんぜんサイトにアクセスできなくなる。

あとその流れで memcache-client のソースも読んだ。 MemCache#get_server_for_key(key) で、あるキーの値がどのサーバに格納されてるかがわかる。このメソッドは protected なので実際には memcache.send(:get_server_for_key, key) のようにして呼び出す。これは上記の「セッションが格納されてるノードがダウンしてるとどうなる?」をテスト環境で調べるときにデバッグ用で使った。確実に特定のノードに保存されてることを確認してからダウンさせる、みたいな検証をしたかったため。

で、 memcache-client は内部的には key を crc32 ナントカいうやり方で数値化した状態でもっていて、格納先ノードを選ぶアルゴリズムはその数値の剰余をとる感じになっていた。 key % servers.size 的な。なので servers が増減すると格納先がずれるということ。あと重み付けができて、例えばあるノードだけメモリが潤沢なので多めに格納したいとかを実現するためにあるのだと思う。 option に weight を渡せるんだったかな。これの実現方法も至極単純で、 pool に servers のノードを push するのだけど weight 回数分 push してるので選ばれる機会が増えるという寸法。