【TECH BLOG #63】サーバーにおけるキャッシュについて

こんにちは。
グリーエンターテインメント株式会社のTAです。
今回は、私が担当しているタイトルで使用しているサーバーのキャッシュについて紹介させていただきます。
キャッシュとは
キャッシュとは、データを保管し、データの取得を高速化する仕組みです。
キャッシュにはいくつも種類があり特徴があります。
今回、私が所属しているチームで運営しているサービス(以下運営サービス)のサーバーのキャッシュについて紹介したいと思います。
Memcached
Memcachedはオープンソースの分散型キーバリューインメモリデータストレージシステムです。
このキャッシュシステムの主な特徴としては以下の通りです。
●応答速度が速い
〇メモリ上にデータを格納しているのでデータを取り出す速度が速い
●key-valueストア
〇キーと値のペアでデータ管理
●揮発性
〇メモリ上にデータを保管しているため、ハードウェアの電源が停止したり、Memcached自体が停止された場合、保管データが消えるので揮発性は高い
●スケーリング
〇スケールアップ、スケールアウトが可能
■ElastiCacheのノードを増やしてスケールアウトが可能
■マルチスレッドなのでノードのスケールアップが可能
揮発性が高いため、運営サービスでは重要なデータを保持せず、消えても問題がないデータや再取得が可能なデータを保管する用途で使用しています。
なお、運営サービスでは以下の目的でMemcachedを使用しています。
●データベースへのアクセス頻度を下げる
〇データベースに保管されている更新頻度の低い静的データをキャッシュしデータを取得できるようにすることでデータベースへの負荷を減らすことができる
〇運営サービスのゲームだと、マスターデータは運営チームがデータベースに入力しない限り更新されないデータなので、ユーザーがアクセスしデータベースからマスターデータを取得したらMemcachedに保管し、次回以降Memcachedからデータ取得できるようにする
●データの取得処理の速度を速くする
〇データベースよりもMemcachedからデータ取得する速度が速い
〇運営サービスのゲームだと、頻繁にデータ処理で使用するユーザーの情報をMemcachedに保管し、データを使用する際は高速で取得し、データ処理の処理速度を高めます
●処理上で生成したデータを別の処理で再利用する
〇運営サービスのゲームだと、バトル処理のプロセスとバトル結果画面のプロセスが異なる場合、バトル処理のプロセスでバトル内容をMemcachedに保管し、バトル結果画面のプロセスでMemcachedから取得してバトル結果を表示します
このようにして無駄な処理、無駄なデータベースへのアクセスを回避し、インフラへの負荷が上昇しないよう対策をとっています。さらに運営サービスではAmazon Web Service(以下AWS)のElastiCacheを用いてMemcachedを導入しているので、以下の図のように、複数のEC2インスタンスから共通のMemcachedからキャッシュデータを取得します。(EC2インスタンス自体にMemcachedをインストールすることも可能です。)

運営サービスにおいてお客様がアクセスする環境は、ElastiCache上のMemcachedを使用することで複数のEC2インスタンスから独立した仕組みにしています。一方、運営メンバーのみアクセスできる開発用の環境では、EC2インスタンス自体にMemcachedをインストールし、Memcachedを用いた開発、検証を行っています。
Redis
RedisとはRemote Dictionary Serverの略で、Memcached同様、分散型キーバリューインメモリデータストレージシステムです。
Memcachedとの違いで言うと以下の通りです。
●シャードという概念がある
〇複数のElastiCacheのノードのグループ
〇Redisではノードの役割としてPrimary NodeとReplica Nodeがある
■Primary Nodeは読み取り/書き込みができる
■Read Replicaは読み込みだけできる
〇1シャードにつきprimaryは1つ、replicaは5つまで設定できる
〇クラスターモードが有効だとシャードを複製設定できるが、無効だとシャードは1つしか設定できない
●揮発性
〇メモリのみ使用した保管方法だと揮発性は高いが、永続化する仕組みもある
■メモリ上にデータを保管しているため、ハードウェアの電源が停止したり、Redis自体が停止された場合、保管データが消える
■以下のような仕組みで保管データの永続化も可能
●RDBベース
〇定期的にストレージにキャッシュのスナップショットを保管する仕組み
●AOFベース
〇Redisへの書き込み処理を実行するたび、書き込みログを保管する仕組み
●スケーリング
〇スケールアップ、スケールアウトが可能
■クラスターモードが無効だとシャード1つ分のRead Replica Nodeのスケールアウトが可能
■クラスターモードが有効だと複数シャードによりスケールアウトが可能
●Sorted sets(ソート済みセット)
〇あるkeyに対してvalueを複数セットするとvalueの大きさでデータがソートされるデータ構造
〇昇順、降順でソートして取得することも可能
〇運営サービスではこのデータ構造を使用
運営サービスでは揮発性を下げる手段はとらず、後者のSorted setsを用いた機能開発を行っています。
Sorted setsを用いた事例として、ゲーム内のランキング機能開発で使用しています。
ユーザーのランキングのスコア更新をするたび、リアルタイムで順位の変動が可能となり、バッチ処理による集計を行う必要もなくリアルタイムランキングの開発が容易になり、データベースへの負荷を減らすこともできます。
ただし同スコアのとき、keyの文字列のASCIIコード順で並ぶため、この動作仕様に対する対策が必要です。運営サービスでは、スコアの文字列の後ろにランキングイベント終了までの時間を追加し、同スコアでも早く到達したユーザーが上位になるように対策をとりました。
さらにRedisもElastiCacheを用いて導入しているので、以下の図のようにMemcached同様、複数のEC2インスタンスから共通のRedisからキャッシュデータを取得します。(RedisもMemcached同様、EC2インスタンス自体にインストールすることも可能です。)

運営サービスにおいてRedisを図のようにElastiCache上のRedisを利用するのか、それともEC2インスタンスにインストールし利用しているかは、Memcached同様、お客様がアクセスする環境ではElastiCache上のRedis、運営メンバーのみのアクセスする環境ではEC2インスタンスへインストールし利用しています。
APCu
APCuとはAlternative PHP Cache User Cache、PHPで動くインメモリデータストレージシステムでPHPのライブラリの一種です。
このキャッシュは各EC2インスタンスのメモリにデータを保管するので、以下の図のようにEC2インスタンス毎に保管されるキャッシュが異なり、EC2インスタンス間でキャッシュを共有できません。

運営サービスでは、SQLのSELECTクエリから列情報やWHERE句の情報からキーを生成し、取得したレコード情報を前述したキーで保管し、再度同一のクエリを実行する際にはキャッシュからレコード情報を取得し、データベースへのアクセス頻度を下げる仕組みをAPCuを用いて実装しています。
この仕組みにより、ユーザーがデータベースから取得したことのあるマスターデータやユーザー情報を、同じEC2インスタンスで再度取得する場合、データベースからデータを取得せずEC2インスタンスのメモリから再取得ができます。
これからの展望
キャッシュにも種類が多く、性質が異なるものも多々あるので、うまく利用することでインフラ面でのパフォーマンスチューニング、機能開発をするにあたっての近道に繋がります。逆にキャッシュの性質を理解せずに実装してしまうことで、不具合やパフォーマンス低下の原因となってしまうこともあります。
キャッシュ自体の特徴、キャッシュを運用しているインフラ構成を把握した上で、最適なキャッシュを選び、運用に組み込み、サービスの品質向上を目指すことができます。
最後まで読んでいただきありがとうございました。
本件に関するお問い合わせ先
グリーエンターテインメント株式会社 広報担当
東京都港区六本木6-11-1 六本木ヒルズゲートタワー
E-mail:info-ent@ml.gree.net