what:
Google提供的一个开发工具包,里面有很多好用的Java开工具,比如我们本文讲的Cache缓存能力。
引用方式如下:
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>19.0</version> </dependency>
guava-cache对比常用的缓存数据库就是Redis和Memcache:
Redis和Memcache极其适合在微服务架构下做缓存使用。速度是极高的,但是跟本地缓存来比,还是算慢的。
本地缓存其实就相当于一个Map集合,本地缓存获取没有网络IO。但是最大的缺点是每台服务器的本地缓存是不能共享的。
为何不直接使用Map:
如果数据量瞬时或者数据积累量很大,很容易就直接就把Map撑爆。导致内存溢出,服务宕机下线风险。除非数据只有一点点。
guava-cache具备的能力:
1、控制数据量大小;
2、控制数据生命周期;
3、如果能做些数据命中率统计更好了;
how:
大体流程:
GuavaCache的工作流程:获取数据->如果存在,返回数据->计算获取数据->存储返回。
由于特定的工作流程,使用者必须在创建Cache或者获取数据时指定“不存在数据时应当怎么获取数据”。GuavaCache采用LRU的工作原理,使用者必须指定缓存数据的大小,当超过缓存大小时,必定引发数据删除。GuavaCache还可以让用户指定缓存数据的过期时间,刷新时间等等很多有用的功能。
类结构:
GuavaCache并不希望我们设置复杂的参数,而让我们采用建造者模式创建Cache。GuavaCache分为两种Cache(如下)。LoadingCache继承了Cache,LocalLoadingCache是 其实现类。它可以定时刷新数据,因为获取数据的方法已经作为构造参数方法存入了Cache实例中。同样,在get时,不需要像LocalManualCache还需要传入一个Callable实例。
LocalManualCache和LocalLoadingCache,两者唯一的区别就是LocalLoadingCache extends LocalManualCache implements LoadingCache<K,V>接口。
注意:LocalManualCache和LocalLoadingCache两者都是对LoaclCache的包装,而LocalCache就是一个缓存的存储器,通过继承AbstractMap和实现ConcurrentMap接口,实现了支持并发的本地map(可以看成类似的ConcunrrentHashMap),LocalCache不对外暴露。
清理缓存时间:
只有在操作数据时,才会清理缓存LRU,或者使用者可以单起线程采用Cache.cleanUp()方法主动清理。
即:使用CacheBuilder构建的缓存不会"自动"执行清理和回收工作,也不会在某个缓存项过期后马上清理,也没有诸如此类的清理机制。相反,它会在写操作时顺带做少量的维护工作,或者偶尔在读操作时做——如果写操作实在太少的话.
刷新:
主动刷新方法LoadingCache.referesh(K)
显示插入:
使用cache.put(key, value)
方法可以直接向缓存中插入值,这会直接覆盖掉给定键之前映射的值.
缓存权重:
不同的缓存项有不同的“权重”(weights),你可以使用``CacheBuilder.weigher(Weigher)指定一个权重函数,并且用
CacheBuilder.maximumWeight(long)`指定最大总重.
存储原理:
Segment数组 + ReferenceEntry数组(AtomicReferenceArray) + 链表(ReferenceEntry)
特性:
cache不能返回null的value:
get时,key不存在返回null,返回null。
get时,key存在,缓存的value不为null,返回非null值。
可以通过get的value==null,来判断加载时机(即:通过value为null作为是否加载缓存的标准。反之,如果缓存的是null,那么即使加载过一次,但是每次get时,同样会再加载一次,这样就没有起到缓存的作用)。