本稿は「ソシャゲ開発経験から学んだゲームに Redis を使う際の Tips」をもとに加筆・補正し、文章を整えました。
近年のKVSでは割とRedisが覇権を取っていることもあり(当社比)、社内の多くのプロジェクトでRedisを使用するようになりました。ということでノウハウ的なのも溜まってきたのでまとめてみます(大量のユーザーデータを扱うソーシャルゲームにしか当てはまらない部分もあるかと思います)。
単純にパフォーマンスをRDB < Redisと思い込んでとりあえずでキャッシュしない
「Redisは速い」と言われますが、インデックスをきちんと貼ったRDBのクエリもそこまで遅いわけではありません。結局通信コストの方が遥かに大きいので、内部の取得時間差はトータルで考えると多くの場合誤差です。特にRDBの主キーのみで取得できるようなデータを、Redisにキャッシュすることにメリットはありません。キャッシュするコードを書くコストの方が高くつきます。キャッシュするのは、RDBの複数テーブルを参照しなければならないような、時間のかかるかつアクセス頻度が高いクエリに対して行いましょう。
基本的にExpireはつける
Redisはデータを永続化できることも特徴ですが、逆に言えば消えないためディスク容量はどんどん圧迫されていきます。永続性が必要ないものについては、Expireをつけることにより、ディスクが食いつぶされるのを幾分か防ぐことができます。とくに、キャッシュの場合は必須です。
そもそも容量を圧迫しないように設計する
Expireはあくまで有効期限なので、短期間に大量アクセスが来れば、データ設計によってはやはり容量不足になることもあります。ですから、そうそうデータが爆発しないように設計しておきましょう。ユーザーが何かアクションするたびにレコード増えるような設計は厳禁です(ユーザーがクエストに行くたびに1レコード増えるなど)。
基本的にユーザーと機能に対してデータ量が1:1になるようにしておけば、データ量が一気に増加しにくいですし、データ量の把握もしやすいです(少し前のゲームによく見られた「1日1回フレンドにあいさつする」という機能で、1あいさつ1レコードつくったためにKVSの容量が膨大になった、という事例があったそうです)。
永続データ
RedisとRDBのデータを同時一括更新しないようにする
RedisのデータとRDBのデータの同時更新でエラーが起きた場合、RDBのデータはトランザクションに守られていますが、Redisのデータは手動ロールバックが必要になります。実装的にもメンテナンス性もよくないので極力避けるべきです。
そもそもエラー時にロールバックしなければならないようなデータは、Redisに入れるのを避けるべきかもしれません。エラーが出たらそのデータは一旦削除、くらいの気軽さがあった方がいろいろ楽です。
Redisにユーザーの永続データを入れるのを避ける
前項目に若干関係しますが、ユーザーの永続データは入れない方がいいです。ユーザー数は広告効果等である日大量に増加したりするので、思わぬところで負債が産まれたりします(RDBの負荷分散はバッチリだったけどRedisの負荷分散は考えてなかった!とか。負荷分散するにはデータを一旦消さなきゃ!でもユーザーデータだから消せない!とか)
そもそもRDBがあるのに、わざわざRedisを永続データの保存先に使う必要は基本的にないはずです(でもちょっとしたパラメータが、気づいたらなぜかRedisのみに保存されるようになってたりします。git blameしなきゃ)。
ユーザーデータでない永続データは設定系でしょうか...(例が出ません)。ユーザーデータ以外なら、開発側である程度データ量の制御ができるので、便利に使えるなら使ってもよいかと思います。
ゲームにおけるRedisの使い所
キャッシュ
KVSなのでキャッシュが一番に思いつきますが、前述のとおりキャッシュ対象は吟味しましょう。もちろんExpire必須!あと、負荷が高いときはスケールアウトできるようにしておくといいです。Redisはスケールアップよりスケールアウトの方が効果が高い気がします(シングルスレッドだからか、コア数など増やしても、そこまでパフォーマンスは上がらなかった経験があります)。各言語のRedisライブラリも割とシャーディング対応しています。大体がキーのハッシュ値から各シャードに振り分ける実装になっているため、キャッシュサーバーの増減もしやすいです。
ランキング
ソート済みセットを使ったランキング実装はRedisの有効な使い方です。各ユーザーのポイントはDBに保存してあるはずなので、何かあったらランキングは集計し直せばいいだけという点もgood!(同点問題は管轄外です)
レイド(みんなでボスを殴るやつ)
複数ユーザーで一体のボスを倒すようなものは、ボスの体力減少のレースコンディションがやっかいですが、Redisのincrby、decrbyはアトミックなためみんなで一斉に殴っても大丈夫です(やったぜ)。
最後に
以上になります。Redisは便利ですがデータの保存先としてはRDBに寄せた方が運用しやすいです。Redisの中身は吹っ飛んでも最悪作り直せばOKという設計にしておくと精神的に楽です(別にRedisのデータが吹っ飛びやすいとか言ってるのではなく、死守しなければならないものが多いと大変ということです)。
Top comments (1)
素晴らしい