🕌

Redis Cacheを整理する話

2023/12/28に公開

はじめに

AppBrewでエンジニアインターンをさせていただいているshihoと申します。主にWeb版LIPSの開発をしています。

背景

今回は、redisのキャッシュ使用量増大のアラートが最近鳴っていたので、redisのキャッシュ整理に取り組みました。

分析

現状をredis-inventoryを用いて分析します。これは、Redisのキーをプロファイリングし可視化するツールであるobukhov氏のredis-inventoryを、CTOのPinさんがforkしプロファイリングを並行処理で高速化したものです。 redisの使用内訳のjsonファイルを得ることができ、得られたデータを可視化することもできます。

代表的な使い方は、以下のようです。詳細は、こちらをご覧ください。

  • コンパイル
    • レポジトリをcloneして、go buildを実行し、redis inventoryのバイナリを作る
  • インデックスを構築
    • ./redis-inventory index <[r](http://lips-production.vp8ixs.ng.0001.apne1.cache.amazonaws.com:6379/)edis_host> --separators=":/" --throttle 1000000 --scanCount 1000 --pattern 'objects:*' など。
    • osのtmpディレクトリにjsonファイルが作成されます。
  • データを可視化
    • 表として表示する場合
      • ./redis-inventory display
    • 階層的な円グラフで表示する場合
      • ./redis-inventory display -output=chart
    • osのtmpディレクトリにあるjsonファイルを参照して図示します。

また、このコミットのように変更すれば、任意のjsonファイルをパス指定で可視化することができ、結果の比較に便利です!

なお、社内で他のやりかたの検討もされていました。

他のやり方

  • ぐぐると Redis の keys コマンドを使っている記事等が散見されるが、これは危険である
    • LIPS の staging, production 環境のようなキーが多い Redis インスタンスでレスポンスがたくさん返ってくる keys コマンドを使うと、全然レスポンスが返ってこなくなり、CPU 負荷が高くなり、障害につながる
    • 公式にも要注意と書いてある https://redis.io/commands/keys/
  • redis-cli の bigkeys オプションを使えば、単独で大きなメモリを使っているキーを見つけられる。ただし、これは小さなキーがたくさんあって大きなメモリを使っているケースを見つけることができない
  • scan を使ったランダムサンプリングは、おそらく取得するキーに偏りが出る。また、件数のみの調査で、ここではメモリ使用量の調査ができていない
    • https://redis.io/commands/randomkey/ を使うと上手くランダムサンプリングできるかも。フルスキャンには実行時間めちゃめちゃかかるので有用そうではある

可視化の結果は以下のようでした。

全体の中で、Objects、それも大半はUser関連のCacheが占めていることがわかります。

補足

  • redis-objectというgemを使ってUserごとにキャッシュを生成しているため上記のようなキーになります。
  • cache-rails-7-0は、rails標準のキャッシュ機能向けに設定したnamespaceです。
  • sidekiqの箇所には、 sidekiqという非同期ジョブ処理の gem が使っているデータが対応しています。

処置

ユーザ関連で、使われていないキャッシュのキーや、アクティブでないユーザのキャッシュを削除しました。また、redisの再起動も実行され、不要なリソースの残存が削除されました。

結果

User関連のCacheは26.6GBから、2.5GBへと大幅に減り、全体の使用量を半分程度に減らすことができました!

なお、メモリの断片化率が高いことが観察されたため、 memory doctorの診断をもとに、activedefragパラメタをonにして、断片化率を下げる、という試みも行われました。

補足

Amazon ElastiCacheのダッシュボードの断片化率の推移は以下のようになりました。

縦の点線が、activedefragをonにした時期に、11/7ごろのピークと急落は、再起動をした時期にあたります。これを見ると、再起動がやはり大きな効果があるようですね。

まとめ

redis-inventoryを用いたredisの負担の分析、対処、結果の検証を行いました!様子を可視化できるのはありがたいですね!

AppBrew

Discussion