缓存的有效期,淘汰策略及一些问题(一)

在如今这个流量迸发的环境下,如何解决大数据场景,高并发,高性能,热点数据访问等优化问题成为了程序员们所想的重中之重,而这时就涉及到缓存问题,这已经不在是简单的key-value存取,在具体的业务场景中,需要很强化的架构设计,而缓冲架构设计不到位的话,受到非正常访问数据冲击,MySQL支撑不住,很容易导致系统崩溃。说到缓冲,脑中的第一反应是否是如下结构?

在这里插入图片描述
缓冲的有效期TTL可以做到数据弱一致性,有效期失效后,保证数据的一致性,节省空间。通常使用的过期策略有三种:

  • 定时过期
    优点:针对设置过期时间的key创建一个定时器,到期立刻清楚,对内容友好。
    缺点:会占用大量的CPU去处理过期的数据,影响缓存的响应时间和吞吐量,所以这里不推荐使用。
  • 惰性过期
    优点:可以最大化地节省CPU资源
    缺点:只有接收到访问请求时,才会判断该数据是否已过期,过期则清除。对内存非常不友好,极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。
  • 定期过期
    优点:调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。
    缺点:假设一种场景,比如有A,B,C,D…等1000W条数据,其中以B为例,每次B数据都逃过扫描,一直扫描不到,但是B数据又没有用,这样也没法对B进行清除,也不太友好。

这时我们可以采用定期过期+惰性删除结合这种方案;比如redis默认每隔100ms检查,是否有过期的key,有则清除,需要说明的是,redis是随机抽取进行检查,因此,采用定期删除策略,会导致很多key到时间没有删除。

于是,惰性删除派上用场。接收到请求查看是否过期,过期则删除,但还有一种情况就是如果定期删除没删除key。然后也没去请求key,惰性删除也没生效。这样,redis的内存会越来越高。

针对这一情况,就需要加入缓存淘汰策略,有两种:LRU,LFU(redis 4.x 后支持LFU策略)

  • LRU(时间)
  1. 新数据插入到列表头部,当缓存命中,则将数据移到列表头部
  2. 假设内存不足时,列表满的时候,列表最末的数据将被淘汰

在这里插入图片描述

  • LFU(频率)
  1. 一个数据在一段时间使用次数少,那么之后一段时间使用的可能性也很小
  2. LFU需要定期衰减

在这里插入图片描述
看图会发现,user4因为基数积累过大,一直没被访问都不会被淘汰,反而近期经常访问的数据却互相淘汰。针对这一情况我们就要采用定期衰减,定期减半,这样没人访问的数据哪怕基数再大都会被淘汰,举个不恰当的例子,要雨露均沾而不能一家独大。

针对淘汰策略符合情况的,使用volatile-lru,当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。
redis默认使用的是noeviction,这一点还需手动配置,其他几种allkeys-lru,allkeys-random,volatile-random,volatile-ttl都不是太友好,这里不多做赘述,读者有想深入了解的可自行查看一些淘汰策略资料。

关于缓存模式,更新方式,缓存穿透及缓存雪崩放在(二)中做一个详细叙述,读者可点击查阅

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值