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

一、背景
线上你写代码的时候,想当然的认为写进 redis 的数据就一定会存在,后面导致系统各种 bug,谁来负责?
常见的有两个问题:
往 redis 写入的数据怎么没了?
可能有同学会遇到,在生产环境的 redis 经常会丢掉一些数据,写进去了,过一会儿可能就没了。我的天,同学,你问这个问题就说明 redis 你就没用对啊。redis 是缓存,你给当存储了是吧?
啥叫缓存?用内存当缓存。内存是无限的吗,内存是很宝贵而且是有限的,磁盘是廉价而且是大量的。可能一台机器就几十个 G 的内存,但是可以有几个 T 的硬盘空间。redis 主要是基于内存来进行高性能、高并发的读写操作的。
那既然内存是有限的,比如 redis 就只能用 10G,你要是往里面写了 20G 的数据,会咋办?当然会干掉 10G 的数据,然后就保留 10G 的数据了。那干掉哪些数据?保留哪些数据?当然是干掉不常用的数据,保留常用的数据了。
数据明明过期了,怎么还占用着内存?
这是由 redis 的过期策略来决定。

3种过期策略

定时删除

含义:

在设置key的过期时间的同时,为该key创建一个定时器,让定时器在key的过期时间来临时,对key进行删除

优点:

保证内存被尽快释放

缺点:

  1. 若过期key很多,删除这些key会占用很多的CPU时间,在CPU时间紧张的情况下,CPU不能把所有的时间用来做要紧的事儿,还需要去花时间删除这些key
  2. 定时器的创建耗时,若为每一个设置过期时间的key创建一个定时器(将会有大量的定时器产生),性能影响严重
  3. 没人用

惰性删除

含义:

key过期的时候不删除,每次从数据库获取key的时候去检查是否过期,若过期,则删除,返回null。

优点:

删除操作只发生在从数据库取出key的时候发生,而且只删除当前key,所以对CPU时间的占用是比较少的,而且此时的删除是已经到了非做不可的地步(如果此时还不删除的话,我们就会获取到了已经过期的key了)

缺点:

若大量的key在超出超时时间后,很久一段时间内,都没有被获取过,那么可能发生内存泄露(无用的垃圾占用了大量的内存)

定期删除

含义:

每隔一段时间执行一次删除(在redis.conf配置文件设置hz,1s刷新的频率)过期key操作

优点:

通过限制删除操作的时长和频率,来减少删除操作对CPU时间的占用–处理”定时删除”的缺点
定期删除过期key–处理”惰性删除”的缺点

缺点:

在内存友好方面,不如”定时删除”
在CPU时间友好方面,不如”惰性删除”

难点:

合理设置删除操作的执行时长(每次删除执行多长时间)和执行频率(每隔多长时间做一次删除)(这个要根据服务器运行情况来定了)

redis的过期策略和内存淘汰机制

1、定期删除+惰性删除

定期删除:指的是redis默认是每隔100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除

惰性删除:在你获取某个key的时候,redis会检查一下 ,这个key如果设置了过期时间那么是否过期了,如果过期了此时就会删除,不会给你返回任何东西

2、如果大量过期key堆积在内存里,导致redis内存块耗尽了,怎么办?

内存淘汰机制:

redis.conf中配置:

1
# maxmemory-policy noeviction

  • noeviction:当内存使用达到阈值的时候,所有引起申请内存的命令会报错。

  • allkeys-lru:在主键空间中,优先移除最近未使用的key。

  • volatile-lru:在设置了过期时间的键空间中,优先移除最近未使用的key。

  • allkeys-random:在主键空间中,随机移除某个key。

  • volatile-random:在设置了过期时间的键空间中,随机移除某个key。

  • volatile-ttl:在设置了过期时间的键空间中,具有更早过期时间的key优先移除。