Redisのメモリ使用量がmaxを超えた場合の挙動

Redisのメモリ使用量がmaxを超えた場合の挙動について検証してみた。

環境: version: 2.4.16

Redisではタイムアウト時間を設定したキーは時間を超えると自動で削除され、タイムアウト時間を設定しないと永続的に保存される。

また、メモリの空き領域がなくなった場合、期限のあるものから削除されていく(デフォルトの設定の場合)。
注意すべき点は、期限が設定されていないキーは削除対象にならないということである。


実際にその挙動を検証してみた。
まず、検証しやすいようにメモリの使用可能な量を以下の値に設定しておく(redis.conf)

#新たにキーを保存した際にmaxmemoryエラーにならないぎりぎりの値
maxmemory 910KB 

maxmemory-policy は 以下を設定

#LRUアルゴリズムを使用して期限切れになったセットのキーを削除
maxmemory-policy volatile-lru

この状態で、メモリがMaxを超えるまでキーを追加していってみる。※期限は設定せずに保存

redis 127.0.0.1:6379> set a 111111111111111111111111
OK
redis 127.0.0.1:6379> set b 111111111111111111111111
OK
redis 127.0.0.1:6379> set c 111111111111111111111111
OK
redis 127.0.0.1:6379> set d 111111111111111111111111
OK
redis 127.0.0.1:6379> set e 111111111111111111111111
OK
redis 127.0.0.1:6379> set f 111111111111111111111111
OK
redis 127.0.0.1:6379> set g 111111111111111111111111
(error) ERR command not allowed when used memory > 'maxmemory' 

7つ目のキーを追加したところでmaxmemoryを超えてエラーになった。
maxmemory-policy : volatile-lru の場合、メモリのMAXを超えた場合は期限切れのものから削除されるが、この場合期限切れのキーが一つも存在しないためエラーになった。

maxmemory-policy がvolatile-ttl, volatile-lru, volatile-random の場合も挙動は同じだった。


maxmemory-policy をallkeys-lru (どれかのキーをランダムに削除) にしてみると

redis 127.0.0.1:6379> set g 111111111111111111111111
OK

追加できた。

キーの一覧を確認すると "a" が消えていた

redis 127.0.0.1:6379> keys *
1) "c"
2) "d"
3) "e"
4) "f"
5) "g"
6) "b" 

allkeys-lruの場合は期限が設定されていなくとも自動で削除されることが確認できた。
LRUアルゴリズムのため、最も使われてないものが削除対象になる。

allkeys-randomの場合も同様

redis 127.0.0.1:6379> set h 111111111111111111111111
OK
redis 127.0.0.1:6379> keys *
1) "c"
2) "d"
3) "e"
4) "f"
5) "g"
6) "h" 

今回は"b"が削除された。

■まとめ
期限を設定していないキーはメモリ使用量がmaxに達した場合に自動削除対象にならない(maxmemory-policyがvolatile-***の場合)ので注意。
キャッシュとしてredisを運用している場合、誤って期限を設定しないキーが保存されてしまうと削除されずに残り続けてしまう。

また、期限を設定していないキーであっても、maxmemory-policyがallkeys-lru、allkeys-randomの場合は削除対象となる。何らかの理由でキーに期限を設定せずに運用する場合はこれらに設定をすればよいと思われる。