以下基于Redis来简单了解下内存淘汰策略和缓存过期策略。
先聊聊缓存过期策略有哪些?
- 定时删除
这是最常见也是应用最多的策略,使用这个策略,每个设置过期时间的key都需要创建一个对应的定时器,到过期时间就立即被清除。这种方式需要耗费大量的CPU资源去处理过期数据,可能会影响到缓存服务的性能,不过它好就好在会立即把过期无用的数据删除了,避免浪费内存。
- 惰性删除
这就是个懒加载的思想,只有当一个key被访问到时,才会去判断这个key是否过期,然后决定是否要进行删除操作。CPU资源时节约了很多,但是如果有好多过期的key就是没有被访问到,那么就会导致内存被白白浪费。
- 定期删除
从以上的两个策略中可以发现,要么就是耗费CPU资源,要么就是浪费内存空间,所以这个策略就是对以上两个策略的一种整合。这个策略会添加一个独立的缓存字典,里面存放的都是设置了过期时间的key,然后每隔一段时间,就扫描一定数量的key(不是全扫描,不然要是key很多,CPU压力就大了),并清除其中已经过期的key,这策略不至于像定时过期策略一样耗费CPU资源,,也不像惰性删除策略一样会浪费内存空间,不过它只是做了个折中的选择,而且即使使用定期过期策略,用户仍然可能会访问到过期的缓存,毕竟不是全扫瞄过期key而且两次扫描之间还有一定的时间间隔。
Redis一般是采用定期删除+惰性删除,使用定期过期策略就不至于浪费太多内存,使用惰性删除策略,就可以防止用户访问到过期的缓存。
这时候可以想想,有了缓存过期策略,就可以保证内存不会被占满么?如果定期删除漏掉了很多过期key,然后这些key也没被查,那也就不会走惰性删除,这样的key越来越多,内存就会被耗尽了。
这时候怎么办?自然得走内存淘汰策略了。
所以可以把内存淘汰策略理解为是对缓存过期策略的补充和兜底,如果缓存过期策略这种温柔的方式处理不了,那么只能由内存淘汰策略来强制淘汰一些数据了,Redis的安全可用才是最重要的。
内存淘汰策略有以下几种
策略 | 作用 |
---|---|
noeviction | 这是默认的策略,当内存不足以容纳新写入数据时,新写入操作会报错,这种策略可以保证数据不丢失 |
allkeys-lru | 当内存不足以容纳新写入数据时,移除最近最少使用的key(这个是最常用的) |
allkeys-random | 当内存不足以容纳新写入数据时,随机移除某个key |
volatile-lru | 当内存不足以容纳新写入数据时,在设置了过期时间的key中,移除最近最少使用的key |
volatile-random | 当内存不足以容纳新写入数据时,在设置了过期时间的key中,随机移除某个key |
volatile-ttl | 当内存不足以容纳新写入数据时,在设置了过期时间的key中,根据key的过期时间来进行淘汰,有更早过期时间的key优先移除 |
volatile-lfu | 当内存不足以容纳新写入数据时,在所有设置了过期时间的key中,移除使用频率最少的key |
allkeys-lfu | 当内存不足以容纳新写入数据时,在所有的key中,移除使用频率最少的key |
总结
内存淘汰策略和缓存过期策略要分清楚,内存淘汰是缓存服务层面的操作,它关注的是如何保证Redis的内存可用,而缓存过期策略则是用来定义具体的缓存数据何时失效,避免无效数据占据内存同时也影响用户体验。