背景
最近ElasticCacheのRedisを利用して、メモリ使用量が常に高い状態になって、メモリ増加した.
その後、メモリ利用量もアイテム数もずっと増え続きしてた
調査
メモリ増加前にメモリ利用量がピックになって、アイテム数がずっと同じ数値でした。
おかしいので、仮説としてRedis利用メモリがMAXメモリ超えた時点で、アイテムがredisから削除されたではないか
REDIS を LRU キャッシュとして使う
こちらを見ると、volatile-lruの場合はexpireが設定されてるアイテムなら、期限切れるかどうかと関係なく利用頻度が少ないアイテムから削除
ローカルで検証してみる
前準備
- こちらを参考にredisインストールMacにRedisをインストールして使ってみる
$ brew install redis
メモリサイズを2MBにして、maxmemory-policyをvolatile-lruにする
期限付きがないアイテムを追加して、最大メモリ超えると、エラーになる
- 設定変更 /usr/local/etc/redis.conf
- maxmemory 2MB
- maxmemory-policy volatile-lru
- 再起動
brew services restart redis
- 有効期限設定しないで10000個アイテムセット
(1..10000).each do |i|
Redis.current.set(SecureRandom.uuid, '1111111111111111111111111111111111')
end
エラーで落ちる
Redis::CommandError: OOM command not allowed when used memory > 'maxmemory'.
redis-cliで追加されるアイテム数確認
dbsize
1570個追加できた
期限付きのアイテムを追加して、最大メモリ超えると、後で回収される
- 1000個の有効期限付きで追加
time = 3.months.seconds
(1..1000).each do |i|
id = SecureRandom.uuid
Redis.current.set(id, '1111111111111111111111111111111111')
Redis.current.expire(id, time)
end
dbsizeで確認、0個、メモリ使いすぎて、削除された?
-
100個を追加
-
正常に追加できた
-
300個を追加
-
正常に追加できた
-
1分ぐらい待つと、207個になってる
-
5分ぐらい待つと、14個
-
回収アルゴリズムがよくわからん
-
500個を追加
-
正常に追加できたが、1分後に0個になった、回収された
結論
- volatile-lruの場合はexpireが設定されてるアイテムなら、期限切れるかどうかと関係なく利用頻度が少ないアイテムから削除、削除アルゴリズムがよくわかってない
- 全部expireが設定されてるアイテムだったら、メモリが少なくなって、redisが落ちることがないが、正確な有効期限までじゃなくても、削除される