rails のセッション管理に memcache を使う方法

rails は 2.X からデフォルトのセッションストアが CookieStore になりました。


ログイン認証のあるアプリケーションだと、セッションにユーザーID入れておいて、

Cookie にオブジェクトを入れるのは危険なので ID だけ入れる)

リクエストごとにユーザー検索をすると思うけど、毎回検索したくないために、

結局 memcache を使ってユーザーをキャッシュしたりする。

それなら、最初から memcache でセッション管理して、

セッションにユーザーオブジェクトを格納すればいいんじゃないの?と思います。


ということでそのやり方のまとめ。


memcache のインストールは省略します。


memcache-client のインストール

gem install memcache-client


environment.rb

(省略)
Rails::Initializer.run do |config|
(省略)
  config.action_controller.session = {
    :session_key => 'セッションキー',
    :secret      => 'ランダムで充分長い文字列'
  }
  config.action_controller.session_store = :mem_cache_store
(省略)
end
memcache_options = {
  :readonly => false
}
memcache_servers = [ 'IPアドレス:ポート番号' ]
SESSION_CACHE = MemCache.new(memcache_servers,
                             memcache_options.merge(:namespace => "アプリケーション名-session-#{ENV['RAILS_ENV']}"))
ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS.merge!('cache' => SESSION_CACHE)


CookieStore から変更したら protect_from_forgery のコメントを外しておきます。

application.rb

class ApplicationController < ActionController::Base
  # Pick a unique cookie name to distinguish our session data from others'
  protect_from_forgery :secret => 'ランダムで充分に長い文字列'
(省略)


どうせ memcache を使うならセッション情報以外のものもキャッシュしたくなる。

その場合、有効期限のあるキャッシュ(例えば1時間や一日)を簡単に利用したい。

そんなとき、弊社ではこんな感じの $HOURLY_CACHE, $DAILY_CACHE を利用してキャッシュしています。(ガチャスポのトップページとか)

# セッションとは別サーバーにする
memcache_servers = [ 'localhost:ポート番号' ]
memcache_options = {
  :readonly => false
}
$HOURLY_CACHE = MemCache.new(memcache_servers,
                             memcache_options.merge(:namespace => "アプリケーション名-object-#{ENV['RAILS_ENV']}"))

$DAILY_CACHE = MemCache.new(memcache_servers,
                            memcache_options.merge(:namespace => "アプリケーション名-object-#{ENV['RAILS_ENV']}"))

def $HOURLY_CACHE.put(key, obj)
  self.set(key, obj, 1.hour)
end

def $DAILY_CACHE.put(key, obj)
  self.set(key, obj, 24.hour)
end


使い方はこんな感じ。

$HOURLY_CACHE.put(:test_key, test)
test = $HOURLY_CACHE.get(:test_key)


追記
タイムアウトの設定を変更したくて、memcache-client-1.5.0 のソースを見ると、

オプションにあると思っていた compression, debug, urlencode がなかった。

よくよく調べてみると、そいつらは rails1.2 まで使用されていた Ruby-MemCache の設定だった。

Ruby-MemCache
http://www.deveiate.org/projects/RMemCache/


memcache-client には、代わりに multithread, request_timeout のオプションがあったけど、request_timeout は現在効いていないみたい。