Help us understand the problem. What is going on with this article?

データサイズが巨大なキーをRedisには作ってはいけない

はじめに

多様なデータの持ち方が可能でRead/Writeも高速。
キャッシュDBとして優秀且つ便利なRedisですが、しっかりデータ設計をしないと痛い目をるという体験談を自害の念も込めて書きます。

アプリケーション速度が激しく遅くなった

ea271988-d908-b222-151d-97125254d404.png
アプリケーションの速度が劣化しているときのnewrelicによるパフォーマンス結果です。
通常であれば100~500msでおさまっていたパフォーマンスが、図の通りアクセスのピーク時に大体3000ms、ひどい時だと4000msを超え、しばしばサービス自体も落ちたりする、とても精神がすり減るような状況に陥ってしまいました。
原因としては、サービス自体がスケールし単純にアクセス量が増えたことによるものでそれ自体は想定内のことだったのですが、今までのインフラ構成でも耐えられると高をくくりチューニングを検討しなかったことがあだとなり、結果、自分の首を絞めてしまいました。

なにをしたか

実際にアプリケーションのどの処理でボトルネックになっているのかをまず調査することにしました。
PHP製のアプリケーションだったのでblackfireを用いて検証したところ、この時点では予想外の箇所、Redisのgetが処理の大半の時間を使っていることがわかりました。

アプリケーションのパフォーマンスが悪くなった原因と対応

理由は単純でした。
実際にRedisのKeyを確認したところ1つのキーに割りあてているデータが1GBを超えているものが多数あり、getで取得する時間が重くなっていたことが原因でした。
ちなみに、Redisはシングルスレッドで動くので1つのプロセスが詰まれば他のプロセスが詰まり渋滞してしまいます。
つまり、アクセス量が増えたことによりプロセスがたまりパフォーマンス速度が悪くなっていたことになります。

そこで、肥大化したKeyを細分化し1つのKeyに割りあてるデータ量を減らしパフォーマンスがどれだけ改善するかを試すことにしました。

結果

16c10f24-5512-404b-b3af-116f7ebf1292.png

ピーク時で3000~4000msだったパフォーマンスが50~75ms、平常時では30ms前後まで下がるという驚異的な改善につながりました。

まとめ

便利なミドルウェアは沢山あります。
ただ、何を使うにしても利用する際には将来を見据えてのデータ設計をちゃんとしようということが痛いほど身に沁みました。。
運用をする上で肥大化する可能性のあるデータなどは、最初の設計時に考慮するか、定期的な見直しやチューニングなどを行うことをお勧めします。

komedawara_omusubi
休日はyoutubeでゲーム実況をみるのが趣味。ダイエットがしたいけどなかなかできない適当なやつ。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away