guava的cache

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)(注意:和JDK7的ConcurrentHashMap类似,见文章:https://www.cnblogs.com/sfzlstudy/p/16334418.html

 

 

 

 

 

 

  

特性:

  cache不能返回null的value:

    get时,key不存在返回null,返回null。
    get时,key存在,缓存的value不为null,返回非null值。
    可以通过get的value==null,来判断加载时机(即:通过value为null作为是否加载缓存的标准。反之,如果缓存的是null,那么即使加载过一次,但是每次get时,同样会再加载一次,这样就没有起到缓存的作用)。

    

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


posted @ 2022-05-30 20:15  修心而结网  阅读(1234)  评论(0编辑  收藏  举报