読者です 読者をやめる 読者になる 読者になる

Codaybook

サーバサイドエンジニアが必死に作成した!発見した!を綴るブログ



Ruby on RailsにてRedisにマスタデータのModelをキャッシュ

ruby on rails redis ruby

とあるシュミレータをruby on rails上で作成することになり、ある処理を何万回、 何百万回と動作させなければいけなくなった。例えば以下の処理が本番環境で動作している。

def cards
  (1..1000).each do |index|
    index.to_s + ": " + Card.all[Random.rand(Card.all.size)].name
  end
end

1000回ほど、カードというマスタデータのnameカラムをランダムに1件ずつ取得している処理だが、

Completed 200 OK in 17243ms (Views: 29.3ms | ActiveRecord: 2451.8ms)

ぐらいの処理時間になってしまう。特にActiveRecord: 2451.8msは1回の処理でmysqlに アクセスしてしまうためにモデルデータをなんとかキャッシュできないかと考えなければいけない....!
というわけでruby on railsredisを導入し、モデルデータをキャッシュしてしまおうと対応にでた。

def cards
  (1..1000).each do |index|
    cache = Rails.cache.fetch("card_data", expires_in: 1.hour) do
      Card.all.to_a
    end
    index.to_s + ": " + cache[Random.rand(cache.size)].name
  end
end

card_dataというkeyのvalueにCardモデルの内容を全てキャッシュするように記述してみました。 (expires_inに関してはTTL時間で1時間だけキャッシングするという記述)

これで処理してみると

Completed 200 OK in 16713ms (Views: 94.6ms | ActiveRecord: 0.4ms)

という結果を得ることができました。なんとActiveRecord: 0.4msという速度になり、logを確認すると mysqlログもなくなりキャッシュからデータを取得できていることも確認できました。 (Views: 94.6msになってるのはなぜ・・)

ちなみに実際、どのようにデータがキャッシュされているかは以下コマンドで確認することができます。

$ redis-cli                   // redisコンソールの起動
127.0.0.1:6379> keys *        // キャッシュされているkey一覧
1) "card_data"
127.0.0.1:6379> get card_data // valueの取得

コマンドは大変!クライアントソフトないの!?っという人もいると思います。(自分のことです...) そういう方はRedis Desktop Managerを使用してみてはいかがでしょうか。 以下のような感じでredisを確認することができます。これは便利!

f:id:nisei275:20160809115244p:plain