はじめに
多様なデータの持ち方が可能でRead/Writeも高速。
キャッシュDBとして優秀且つ便利なRedisですが、しっかりデータ設計をしないと痛い目をるという体験談を自害の念も込めて書きます。
アプリケーション速度が激しく遅くなった
アプリケーションの速度が劣化しているときのnewrelicによるパフォーマンス結果です。
通常であれば100~500msでおさまっていたパフォーマンスが、図の通りアクセスのピーク時に大体3000ms、ひどい時だと4000msを超え、しばしばサービス自体も落ちたりする、とても精神がすり減るような状況に陥ってしまいました。
原因としては、サービス自体がスケールし単純にアクセス量が増えたことによるものでそれ自体は想定内のことだったのですが、今までのインフラ構成でも耐えられると高をくくりチューニングを検討しなかったことがあだとなり、結果、自分の首を絞めてしまいました。
なにをしたか
実際にアプリケーションのどの処理でボトルネックになっているのかをまず調査することにしました。
PHP製のアプリケーションだったのでblackfireを用いて検証したところ、この時点では予想外の箇所、Redisのgetが処理の大半の時間を使っていることがわかりました。
アプリケーションのパフォーマンスが悪くなった原因と対応
理由は単純でした。
実際にRedisのKeyを確認したところ1つのキーに割りあてているデータが1GBを超えているものが多数あり、getで取得する時間が重くなっていたことが原因でした。
ちなみに、Redisはシングルスレッドで動くので1つのプロセスが詰まれば他のプロセスが詰まり渋滞してしまいます。
つまり、アクセス量が増えたことによりプロセスがたまりパフォーマンス速度が悪くなっていたことになります。
そこで、肥大化したKeyを細分化し1つのKeyに割りあてるデータ量を減らしパフォーマンスがどれだけ改善するかを試すことにしました。
結果
ピーク時で3000~4000msだったパフォーマンスが50~75ms、平常時では30ms前後まで下がるという驚異的な改善につながりました。
まとめ
便利なミドルウェアは沢山あります。
ただ、何を使うにしても利用する際には将来を見据えてのデータ設計をちゃんとしようということが痛いほど身に沁みました。。
運用をする上で肥大化する可能性のあるデータなどは、最初の設計時に考慮するか、定期的な見直しやチューニングなどを行うことをお勧めします。