Medley Developer Blog

株式会社メドレーのエンジニア・デザイナーによるブログです

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-toolscsv出力
  3. csvsqlitecsv 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運用ライフの一助になれば幸いです。

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

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