Redis过期策略和内存淘汰机制

原文链接:https://www.cnblogs.com/mengchunchen/p/10039467.html

在日常开发中,我们使用 Redis 存储 key 时通常会设置一个过期时间,但是 Redis 是怎么删除过期的 key,而且 Redis 是单线程的,删除 key 会不会造成阻塞。要搞清楚这些,就要了解 Redis 的过期策略和内存淘汰机制。

过期策略

我们set key的时候,都可以给一个expire time,就是过期时间,指定这个key比如说只能存活1个小时,我们自己可以指定缓存到期就失效。假设你设置一个一批key只能存活1个小时,那么接下来1小时后,redis是怎么对这批key进行删除的?答案是:定期删除 + 惰性删除

  • 定期删除

    redis会将每个设置了过期时间的key放入到一个独立的字典中,默认每隔100ms就进行一次过期扫描:

    1. 随机抽取20个key
    2. 删除这20个key中过期的key
    3. 如果过期的key比例超过了1/4,就重复步骤1,继续删除

    为什么不是扫描所有的key呢?Redis 是单线程,全部扫描岂不是卡死了。而且为了防止每次扫描过期的key 比例都超过 1/4,导致不停循环卡死线程,Redis 为每次扫描添加了上限时间,默认是 25ms。

  • 惰性删除

    定期删除可能会导致很多过期key到了时间并没有被删除掉,所以就得靠惰性删除了。这就是说,在你获取某个key的时候,redis会检查一下 ,这个key如果设置了过期时间那么是否过期了?如果过期了此时就会删除,不会给你返回任何东西。并不是key到时间就被删除掉,而是你查询这个key的时候,redis再懒惰的检查一下,通过上述两种手段结合起来,保证过期的key一定会被干掉。

内存淘汰机制

如果定期删除漏掉了很多过期key,然后你也没及时去查,也就没走惰性删除,此时会怎么样?如果大量过期key堆积在内存里,导致redis内存块耗尽了,怎么办?如果很多key没有设置过期时间,key越来越多导致内存耗尽,怎么办?毕竟Redis也是装在物理机上的,内存始终是有限的,这时就需要内存淘汰机制

Redis 的内存占用会越来越高。Redis 为了限制最大使用内存,提供了 redis.conf 中的配置参数maxmemory。当内存超出maxmemory时,Redis提供了几种内存淘汰机制让用户来选择,可以通过配置maxmemory-policy实现:

  • noeviction:写入请求会报错,但是删除和读请求可以继续。(一般没人用这个)
  • allkeys-lru:在所有的 key 中,移除最近最少使用的key。只把 Redis 当缓存时使用这种策略。(推荐)。
  • allkeys-random:在所有的 key 中,随机移除某个 key。(一般没人用这个)
  • volatile-lru:在设置了过期时间key的字典中,移除最近最少使用的key。把Redis当缓存和持久化时可以使用这种策略。(推荐)
  • volatile-random:在设置了过期时间 key 的字典中,随机移除某个key。
  • volatile-ttl:在设置了过期时间 key 的字典中,优先移除 ttl 小的。

评论