こんにちは、開発本部の後藤です。医療介護の求人サイト「ジョブメドレー」の開発を担当しています。
ジョブメドレーでは各種キャッシュや 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
で指定
また、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
ざっくりとした分析の流れは
のようになります。データベースにインポートさえ出来てしまえば以下のように様々な分析が可能になります。
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運用ライフの一助になれば幸いです。
また、ジョブメドレーをはじめ、メドレーの開発にご興味ある方は、ぜひご連絡ください。 www.medley.jp
メドレーがLTスポンサーを務めるRubyKaigi2018にもお邪魔する予定(たまにブースに立っています)ので、そちらでもお会いしましょう。 rubykaigi.org