15
6

More than 1 year has passed since last update.

Redisのメモリが100%を超えたときの挙動の調査・検証

Last updated at Posted at 2022-05-30

はじめに

社内のプロジェクトでAWSのElasticCache for Redisを利用する機会がありました。
その際、Redisメモリ利用量が100%に達する可能性があったので、そのあたりの挙動について調査・検証してみてみました。

調査

メモリが100%を超えようとする時どうなるのか

Redisはメモリが100%になったとしてもいきなり落ちることはありません。
Redisのメモリが100%になるかmaxmemory設定を超えた時、Eviction という事象が発生します。
Eviction とは直訳すると「立ち退き、明け渡し」的な意味で、既存のキーを削除しメモリを確保する挙動です。

Evictionの設定

Eviction発生によるキーの削除ルールはRedisのmaxmemory-policyという設定で変更することができます。
(ElasticCacheのRedisだとパラメータグループの設定で確認・編集できます)

maxmemory-policy の種類には以下のようなものがあります。キーに有効期限(TTL)があるかどうかなども重要になってきます。

maxmemory-policy ルール
noeviction メモリ制限に達したときに新しい値は保存されず、エラーを返す
allkeys-lru 一番最後にアクセスされたキーを削除してメモリを確保
allkeys-lfu 最も使用頻度が少ないキーを削除してメモリを確保
volatile-lru 有効期限のある、一番最後にアクセスされたキーを削除してメモリを確保
volatile-lfu 有効期限のある、最も使用頻度が少ないキーを削除してメモリを確保
allkeys-random ランダムにキーを削除してメモリを確保
volatile-random 有効期限のあるキーをランダムに削除しメモリを確保
volatile-ttl 有効期限が短いキーから削除してメモリを確保

ElastiCacheのRedisではvolatile-lru がデフォルトの設定になっています。

LRUやLFUアルゴリズムについて、詳しく知りたい方はRedisのドキュメントを見てみてください。

検証

というわけで、次はDocker上でRedisを動かして検証してみます。

検証環境

・Windows 11
・Docker Desktop ver.4.6.1 Engine: 20.10.13
・Redis ver.6.2.6

Redisの準備手順

まず、Dockerを使ってRedis検証用のコンテナを作成します。

// redisのイメージをpull
docker pull redis

// redis検証用のコンテナを作成及び起動
docker run --name redis-inspection -d redis:latest

// redis検証用のコンテナに入る
docker exec -it redis-inspection bash

// redisに接続する
/data#  redis-cli  
127.0.0.1:6379>

次にRedisの設定を確認し、maxmemory-policymaxmemoryを確認します。

/data#  redis-cli  
127.0.0.1:6379> INFO memory
.
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
.

DockerのRedisイメージのデフォルトだとmaxmemoryが0なので無限に保存できてしまいます。
また、noevictionなのでメモリが溢れても自動削除されない設定になっています。

今回は検証なので、わざとメモリがあふれるように一時的にmaxmemoryを1MBくらいに設定しておきます。
(RedisのkeyのSET自体にもメモリが900KB前後ほど必要な模様)

127.0.0.1:6379> CONFIG SET maxmemory 1MB
OK
127.0.0.1:6379> INFO memory
maxmemory:1048576
maxmemory_human:1.00M
maxmemory_policy:noeviction

実験:メモリを溢れさせてみる

ここではnoevictionvolatile-lruのパターンで検証してみます。
方法として、3000回ループして次から次へとkey valueのSETを試みます。

noeviction の場合

:/data# for i in {1..3000} ; do echo ${i}; redis-cli SET ${i} test ; done
.
.
OK
2570
OK
2571
(error) OOM command not allowed when used memory > 'maxmemory'.
2572
(error) OOM command not allowed when used memory > 'maxmemory'.
.
.

途中からエラーが発生するようになりました。

(error) OOM command not allowed when used memory > 'maxmemory'.

2570回を超えた段階でメモリの上限に達し、2571回目からは書き込みエラーとなりました。

volatile-lruの場合

まずはmaxmemory-policyvolatile-lruに変更しておきます。

127.0.0.1:6379> CONFIG SET maxmemory-policy volatile-lru
OK

(有効期限付けないver)

:/data# for i in {1..3000} ; do echo ${i}; redis-cli SET ${i} test ; done
.
.
OK
2570
OK
2571
(error) OOM command not allowed when used memory > 'maxmemory'.
2572
(error) OOM command not allowed when used memory > 'maxmemory'.
.
.

volatile-lruは有効期限のあるキーが削除対象なので、こちらも同様のタイミングで書き込みエラーが発生しました。

(有効期限付きver)
次は全てのkeyに3600秒のTTLを設定して実行してみます。

:/data# for i in {1..3000} ; do echo ${i}; redis-cli SET ${i} test EX 3600 ; done
.
.
2999
OK
3000
OK

書き込みエラーが発生することなく、3000回keyのSETを実行することができました。
メモリが100%超えた後のSETでは、既存のキーを削除しメモリを確保している挙動が確認できました。

まとめ

・Redisはメモリが100%になったとしても、落ちることはない(Evictionが発生する)。
・max-memory-policyの設定によってEvictionの発生ルールを変えることで、100%になった際に上書きするかや受け付けないなどの設定することができる。
・ポリシーによっては、TTL(有効期限)の付け忘れによってキーが削除されないなど予期せぬエラーを生んでしまう可能性があるので注意しておく。

15
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
6