株式会社メドレーDeveloper Portal

2018-05-25

ElastiCache for Redis 運用小話 〜メドレー・ TechLunch〜

こんにちは、開発本部の後藤です。医療介護の求人サイト「ジョブメドレー」の開発を担当しています。

ジョブメドレーでは各種キャッシュや sidekiq の queue 等にElastiCache for Redisを利用しています。

先日、メドレーで定期開催している社内勉強会 TechLunch にて、ジョブメドレーでの ElastiCache for Redis の運用周りのネタや知見について発表しました。本記事では、その中から抜粋してメモリ周りの話について紹介します。

キー削除周りの仕様について

キャッシュとして ElastiCache for Redis を利用していく上でまず把握しておきたいのが、キーの削除周りの仕様です。

Redis 本家の Expiration/Eviction

Expiration については Redis ではキーに TTL を設定することで有効期限を設定することができ、こちら に記載のロジックで削除処理を実施してくれます。

Eviction については Redis 本家の実装では以下のような仕様になっています。Redis 本家ドキュメントはこちら

  • used_memory(アプリが利用しているメモリ量)がmaxmemory値を超え始めたら Eviction が発火し始める
    • maxmemoryredis.conf 指定か CONFIG SETコマンドで設定できる
  • maxmemoryに到達したらどのように振る舞うべきかをmaxmemory-policyで指定
    • noeviction: 容量が必要なオペレーションでは evit せず、エラーとなる
    • allkeys-lru: 常に LRU アルゴリズムで削除対象選定
    • volatile-lru: TTL が設定されたキー内で LRU アルゴリズムで削除対象選定
    • allkeys-random: 常にランダムに削除対象選定して削除
    • volatile-random: TTL が設定されたキー内でランダムに削除対象選定
    • volatile-ttl: TTL が設定されたキー内で TTL

また、ElastiCache for Redis ではまだ 3 系列までしか使えませんが、4 系列では新たにLFUも選択肢に入ってくるようです。

Redis 本家の Eviction の動作仕様としては以下のイメージです。

https://github.com/antirez/redis/blob/3.2.10/src/server.c#L3343-L3357

ElastiCache for Redis ではmaxmemoryは編集できず、その代わりに後述する reserved-memoryreserved-memory-percent)を設定すると Eviction が発火するメモリ量の閾値が変わることから上記周りの実装は AWS 側で手を入れていそうです。

ElastiCache for Redis での Eviction

ElastiCache for Redis では以下のように Redis 本家にはないreserved-memoryという概念があるので注意が必要です。

  • maxmemory はインスタンスタイプによって固定値に設定されている
  • maxmemory変更できない
    • 代わりに reserved-memory or reserved-memory-percent を設定して Eviction 発火メモリ量を設定できる
    • maxmemory - reserved-memory < used_memory で Eviction が発火する
  • 古めのインスタンス(2017 年 3 月 16 日以前作成)では reserved-memory がパラメータとして利用できるが、reserved-memory のデフォルト値は 0byte
    • reserved-memory-percent のデフォルト値は 25%
  • この周辺の AWS 公式ドキュメントはこちら

ジョブメドレーでは単一の ElastiCache for Redis インスタンスで運用対象を減らす戦略を取っています(Redis 本家では用途別に分けて適切にチューニングすることを推奨しているため、将来的にはこの構成は変わるかもしれません)。そのため、キャッシュ利用のキーには必ず TTL を設定し、Eviction policy はvolatile-lruとしています。 そして、少し余裕をもたせて reserved-memory を設定、Evictions メトリクスの監視をしています。

メモリ利用量を SQL で分析する

現在稼働している本番環境上でどのパターンのキーがどの程度のメモリを使っているかを把握したくなる場面に出くわした方もいらっしゃるのではないでしょうか。

ElastiCache for Redis では簡単に RDB スナップショットを取得することができます。このデータをうまく使えば直接本番稼動のインスタンスを触りにいくことなく、手元で安心して分析作業が実施できます。

この分析作業に便利なのが redis-rdb-tools です。このツールは RDB ファイルの内容をもとにキーごとの byte 値を以下のような CSV に出力することができます(size_in_bytesは理論値)。

$ rdb -c memory dump.rdb > memory.csv;
$ cat memory.csv

database,type,key,size_in_bytes,encoding,num_elements,len_largest_element
0,list,lizards,241,quicklist,5,19
2,hash,baloon,138,ziplist,3,11

この csv を以下のように SQLite 等のデータベースに突っ込むことで手元で SQL を使ってメモリ統計の分析ができるようになります。

$ rdb -c memory dump.rdb > memory.csv;
$ sqlite3 memory.db
sqlite> create table memory(database int,type varchar(128),key varchar(128),size_in_bytes int,encoding varchar(128),num_elements int,len_largest_element varchar(128));
sqlite>.mode csv memory
sqlite>.import memory.csv memory

ざっくりとした分析の流れは

  1. 本番環境の daily backup RDB 取得
  2. redis-rdb-toolsで csv 出力
  3. csv を sqlite に csv format で import
  4. SQL で分析

のようになります。データベースにインポートさえ出来てしまえば以下のように様々な分析が可能になります。

sqlite> select sum(size_in_bytes) from memory where key like '%cells%';
XXXXX
sqlite> select count(*) from memory where key like '%cells%';
XXXXX

注意点としては実際に本番稼動しているメモリ量を取得しているわけではないので実測値と値がずれてくることです(感覚的には理論値は実測値の 1/2 ぐらいでした)。こちらの詳細の推定ロジックが気になる方は実装を確認いただければと思います。

ジョブメドレーではこの手法を使って分析することでアプリロジックを修正して不要なメモリ利用の改善等に役立てています。

まとめ

ElastiCache for Redis のメモリ周りを中心とした運用ネタについて紹介しました。

ElastiCache for Redis はとても便利でシュッと設定してそれなりの規模でもなんとなく運用できてしまう手軽さがありますが、油断していると思わぬ落とし穴にはまることもあります。

本記事がみなさまの ElastiCache for Redis 運用ライフの一助になれば幸いです。

また、ジョブメドレーをはじめ、メドレーの開発にご興味ある方は、ぜひご連絡ください。

https://www.medley.jp/recruit/creative.html

メドレーが LT スポンサーを務める RubyKaigi2018 にもお邪魔する予定(たまにブースに立っています)ので、そちらでもお会いしましょう。

https://rubykaigi.org/2018

株式会社メドレーDeveloper Portal

© 2016 MEDLEY, INC.