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 が発火し始めるmaxmemory
は redis.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-memory
(reserved-memory-percent
)を設定すると Eviction が発火するメモリ量の閾値が変わることから上記周りの実装は AWS 側で手を入れていそうです。
ElastiCache for Redis での Eviction
ElastiCache for Redis では以下のように Redis 本家にはないreserved-memory
という概念があるので注意が必要です。
maxmemory
はインスタンスタイプによって固定値に設定されているmaxmemory
は変更できない- 代わりに
reserved-memory
orreserved-memory-percent
を設定して Eviction 発火メモリ量を設定できる maxmemory
-reserved-memory
<used_memory
で Eviction が発火する
- 代わりに
- 古めのインスタンス(2017 年 3 月 16 日以前作成)では
reserved-memory
がパラメータとして利用できるが、reserved-memory
のデフォルト値は 0bytereserved-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
ざっくりとした分析の流れは
- 本番環境の daily backup RDB 取得
redis-rdb-tools
で csv 出力- csv を sqlite に csv format で import
- 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 にもお邪魔する予定(たまにブースに立っています)ので、そちらでもお会いしましょう。