引
近来有次被面试官问及:Redis键值对设置过期时间后,这个key是直接删除还是怎么删除的?
我十分干脆告诉他,直接删除咯,定时器到了就删啦。
其实我这么说也没啥问题的对吧?可能很多人都是这么认为的,因为作为一个Redis的使用者直观的感受就是这样的。
探
在网络上搜索Redis、删除、过期、超时等关键字我们会发现常有人说到:
1.删除策略2.过期策略3.淘汰策略4.逐出策略
不难鉴别:删除策略==过期策略,淘汰策略==逐出策略
研
删除策略
首先网上告诉我们删除策略有三种(当然这个是内存级别的,并不是用户层面的展示)
1.定时删除2.主动删除3.被性删除
有些文章也说定期删除、惰性删除,其实
主动删除==定期删除;被动删除==惰性删除
定时删除:就是我之前说的启动定时器以后到时间以后程序直接在内存里抹去这段数据
主动删除:指的是程序周期性地自检,对那些过期的key在内存里抹去数据
被动删除:指的是每当用户再提及这个key(查看他的有效性或者取值),如果过期就在内存里抹去数据
但是这里就带来一个问题了,既然启动了定时删除那么主动删除和被动删除是不是显得很多余?
淘汰策略
淘汰策略很明了,我直接引用了,包括八种:
- noeviction:当内存使用超过配置的时候会返回错误,不会驱逐任何键
- allkeys-lru:加入键的时候,如果过限,首先通过LRU算法驱逐最久没有使用的键
- volatile-lru:加入键的时候如果过限,首先从设置了过期时间的键集合中驱逐最久没有使用的键
- allkeys-random:加入键的时候如果过限,从所有key随机删除
- volatile-random:加入键的时候如果过限,从过期键的集合中随机驱逐
- volatile-ttl:从配置了过期时间的键中驱逐马上就要过期的键
- volatile-lfu:从所有配置了过期时间的键中驱逐使用频率最少的键
- allkeys-lfu:从所有键中驱逐使用频率最少的键
通过查看redis.cof配置文件知道:
默认的策略是noeviction,因此还是推荐配一下的。还可以看到maxmemory-policy上面有一个maxmemory <bytes>
默认为0,表示"无限制",因此也是我们需要去配一下的,否则有可能导致程序把电脑的内存吃完。
这两个参数是相互配合完成内存淘汰的,当程序检测到内存大于等于最大内存时就会启动淘汰策略去清内存了。
明
思考下面这个问题
1.删除策略和淘汰策略是什么关系?
2.启动了定时删除那么主动删除和被动删除是不是显得很多余?
因为要触发淘汰的前提是内存使用量达到配置中的最大内存,所以不难猜测,删除策略是要先于淘汰策略发生的。
启动定时器十分消耗CPU资源,许多文章也提到没人用这个策略。但是可能这么说还是有点文不达意,如果我就是要用呢?但是找遍了配置文件我们也找不到删除策略的选择配置,说明官方是不支持删除策略可配置的。
但是我们可以找到hz这个参数默认值是10,其实就是主动删除的频率是10hz啦(这个不难找资料,也不难理解)。
但是直到这里我们还是不知道Redis是使用了哪一些删除策略,是三个都有还是仅有其中一两个?
好!到这里我们知道三个有用信息:
1.Redis的删除策略是不可配的。
2.Redis的主动删除策略是可以配置频率的。
3.定时删除十分占用CPU资源
那么让你设计一个Redis,你会怎么设计?
通过3我们会把定时删除从方案中剔除,通过2我们知道肯定有主动删除。
那么只使用主动删除好吗?
答案是不够好。因为主动删除带来了周期性的CPU波峰波谷,那么存在一个削峰的方案就是被性删除,这个是零散地处理,因此这样就可以适当地减轻CPU负担了。
最后我们通过查看Redis源码或者使劲挖文章,也可以验证我们地看法:
Redis的删除策略是:主动删除+被动删除,没有定时删除。
到这里我们就可以和面试官对线了:
在用户层面Redis的键值对过期以后会直接被程序删除,因为Redis的删除策略是主动删除和被动删除相结合的。
1.如果键值对过期时,用户去查看这个键,那么就会触发被动删除,因此他就马上被从内存抹去,你是看不到值的。
2.如果你不去查看就会让这个键值对多活那么零点几秒,一旦到达主动删除点,他也会湮灭。
说到这里其实可以结束了,但是既然你知道得多就多说点呗
并且这也不是说键值对没过期就代表他们不会被删除,这是需要看当前Redis配置的是哪一种淘汰策略。
如果配置的淘汰不是默认的noeviction,有别的用户试图插入新的键值对而当前内存使用量已经达到配置的最大值,既过限,会触发程序启用淘汰策略。那么就有几率把你要查的这个还未过期的值清除。
那么说得深入亿点,你很需要知道这个值之前是多少要怎么办呢?
这个就涉及到Redis的持久化了,分两种:
1.RDB 快照
2.AOF日志
看名字也知道他们是干什么的了吧,我就不详细解释了,并且也都是支持在配置文件中配置的。
但是哪一种可以看他之前的值呢?
我们知道:RDB是覆盖式的,AOF是追加式的。
所以显而易见,要看AOF日志才能知道之前的值是多少啦。
末
末了,谢谢你的阅读,希望我的文章对你的学习有所帮助。