Railsでのお手軽なキャッシュ戦略

キャッシュの主な動機は、

  • パフォーマンスの向上
  • より多くのトラフィックを捌けるように
  • サーバー・リソースの節約

が主だとおもう。 今回、Webメディアの運用が決まったあたりで、サーバーサイドのキャッシュを真面目に考えてみたので記録を簡単に残しておく。

キャッシュで気をつけるべき点

キャッシュで気をつけるべき点はもうキャッシュコントロールの一言に尽きる。 これを気をつけていい感じに取ってパフォーマンスを向上させるのが今回のお仕事。

主にRailsでのキャッシュ戦略について

  1. Railsでフラグメントキャッシュを取る
  2. Railsでページキャッシュを取る
  3. Nginxでキャッシュをとる

あまり調査 -> 実装 -> リリースまでの時間がなかったことから、お手軽に対応できそうな方法を中心に検討してみることにしました。

今回、CDNでのキャッシュ戦略は取っていないが、有効な手段だと思う。 後日検証を行って追加する予定である。順を追って簡単に説明する。

フラグメントキャッシュ

キャッシュコントロール

キャッシュ効果 ◯

Railsで一番ポピュラーに取られている(と思われる)キャッシュ手法である。

ただ、どうしてもWebアプリケーション(というかUnicornやPuma)で処理を行う以上、 前段のNginxで処理を完了させるキャッシュの方式よりも効果は少ない。 とはいえDBへのアクセスは減らせるのと、キャッシュコントロールの難易度が他に比べるとかなり楽にできるので、 ログイン処理のような動的コンテンツがあるようなWebページでも導入が容易だと思う。

その他のやりやすさ

他にもサーバーサイド側でデバイス判定して、 HTMLの出し分けだったりでどうしても動的な処理がサーバーサイド側で発生する場合でもそこまで心配せずに導入することが可能。 また、HTMLの一部分だけをキャッシュするという手法も取れるので他の手法に比べて考える事、 キャッシュを取ることによってできなくなることはほとんど無いように感じる。

ページキャッシュ

キャッシュコントロール

RailsRuby)側でのファイル操作が可能なので、記事を更新したときに更新した記事だけの、ページキャッシュを削除したりということがひとまず可能。 後述するNginxのキャッシュよりもキャッシュのコントロールが幾分ラク。 ただどうしても静的ファイルとして出力するので、色々柔軟性には欠ける。

キャッシュ効果 ◎

静的ファイルを直接nginxから呼び出せば効果はばつぐんだ。

その他のやりやすさ

サーバーサイドでデバイス判定して、ページ構成を変更しているようなページを処理するときには注意が必要。 それぞれで異なるページキャッシュを作らないと行けないし、PC用のページキャッシュは必ずPCに、SP用のページキャッシュを必ずSPに返すために工夫が必要だし、 ドキュメントだけを眺めてもそのやり方は書いていないので、自前で実装と言うか工夫が必要になる。 後述するnginxのキャッシュの方がオフィシャルにデバイスによって取得するキャッシュキーを変更できる機能を持っている分、nginxのキャッシュの方が良いのではないか?と思っている。

nginxのキャッシュ

キャッシュ効果 ◎

当然ながらキャッシュの効果は絶大。 Railsのページキャッシュとのスピード面の計測はしていないけど、まぁ変わらないのではないかと思っている。

キャッシュコントロール ×

ただキャッシュのコントロールについては良くないと思っており、 どこかを更新した際には、nginxのすべてのキャッシュファイルを削除するしか無いと思っている。(どのファイルがどの記事のキャッシュかを判別する情報がない) ただ、NginxでキャッシュをとりつつRailsでSessionのブラウザCookieベースで管理する場合、 色々工夫が必要で大変なので、CookieベースのSession管理を取りやめRedisやDBでSessionをStoreする方が良いかもしれない。

結局どの戦略を取ったか

動的に便利にやりたい部分があったというのと、実装までに期間が余り取れなかったという理由もあって、ひとまずフラグメントキャッシュで様子を見てみようということにした。 動作として特に問題が発生していないのと、結構潤沢にサーバーを使える環境というのもあったので、この方法で対応した。

そして、1000万以上PVくらいのWebメディアを半年くらい運用していたのだけどとりたてて問題は発生しなかった。 とりあえずDBアクセスをなくすだけでも効果は絶大なんだな、ということを実感しました。

予算等の見直しや要件に変更が入った場合は2や3への変更を視野に入れる必要もあったのかな、と思っている。

まとめ

  • キャッシュは色々便利だけど、最初はなるべくキャッシュは利用しない方向でできるだけ頑張る
  • 最初は簡単なのでフラグメントキャッシュから始めるといいです。
    • nginxのページキャッシュやRailsのページキャッシュの導入はその後検討でいいと思う。