java guava cache_使用Guava cache构建本地缓存

前言

最近在一个项目中需要用到本地缓存,在网上调研后,发现谷歌的Guva提供的cache模块非常的不错。简单易上手的api;灵活强大的功能,再加上谷歌这块金字招牌,让我毫不犹豫的选择了它。仅以此博客记录我在使用过程中的点滴。

什么是本地缓存

在我们的应用中,大部分的计算是昂贵的,而且是可复用的,并且计算结果不会经常发生改变。这时候我们就可以将这些昂贵的计算结果缓存到内存中,下次使用的时候直接取出即可,而不用重新计算。这样可以节省大量的cpu和内存资源,提高系统的吞吐量。

本地缓存作用就是提高系统的运行速度,是一种空间换时间的取舍。它实质上是一个做key-value查询的字典,但是相对于我们常用HashMap它又有以下特点:

并发性;由于目前的应用大都是多线程的,所以缓存需要支持并发的写入。

过期策略;在某些场景中,我们可能会希望缓存的数据有一定“保质期”,过期策略可以固定时间,例如缓存写入10分钟后过期。也可以是相对时间,例如10分钟内未访问则使缓存过期(类似于servlet中的session)。在java中甚至可以使用软引用,弱引用的过期策略。

淘汰策略;由于本地缓存是存放在内存中,我们往往需要设置一个容量上限和淘汰策略来防止出现内存溢出的情况。

缓存的最大容量与淘汰策略

由于本地缓存是将计算结果缓存到内存中,所以我们往往需要设置一个最大容量来防止出现内存溢出的情况。这个容量可以是缓存对象的数量,也可以是一个具体的内存大小。在Guva中仅支持设置缓存对象的数量。

当缓存数量逼近或大于我们所设置的最大容量时,为了将缓存数量控制在我们所设定的阈值内,就需要丢弃掉一些数据。由于缓存的最大容量恒定,为了提高缓存的命中率,我们需要尽量丢弃那些我们之后不再经常访问的数据,保留那些即将被访问的数据。为了达到以上目的,我们往往会制定一些缓存淘汰策略,常用的缓存淘汰策略有以下几种:

FIFO:First In First Out,先进先出。

一般采用队列的方式实现。这种淘汰策略仅仅是保证了缓存数量不超过我们所设置的阈值,而完全没有考虑缓存的命中率。所以在这种策略极少被使用。

LRU:Least Recently Used,最近最少使用;

该算法其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。

所以该算法是淘汰最后一次使用时间离当前最久的缓存数据,保留最近访问的数据。所以该种算法非常适合缓存“热点数据”。

但是该算法在缓存周期性数据时,就会出现缓存污染,也就是淘汰了即将访问的数据,反而把不常用的数据读取到缓存中。

为了解决这个问题,后续也出现了如LRU-K,Two queues,Multi Queue等进阶算法。

LFU:Least Frequently Used,最不经常使用。

该算法的核心思想是“如果数据在以前被访问的次数最多,那么将来被访问的几率就会更高”。所以该算法淘汰的是历史访问次数最少的数据。

一般情况下,LFU效率要优于LRU,且能够避免周期性或者偶发性的操作导致缓存命中率下降的问题。但LFU需要记录数据的历史访问记录,一旦数据访问模式改变,LFU需要更长时间来适用新的访问模式,即:LFU存在历史数据影响将来数据的“缓存污染”效用。

后续出现LFU*,LFU-Aging,Window-LFU等改进算法。

合理的使用淘汰算法能够很明显的提升缓存命中率,但是也不应该一味的追求命中率,而是应在命中率和资源消耗中找到一个平衡。

在guava中默认使用LRU淘汰算法,而且在不修改源码的情况下也不支持自定义淘汰算法,这算是一种小小的遗憾吧。<

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值