`

本地缓存-应用级缓存之Guava Cache

 
阅读更多

参考:

1.http://blog.csdn.net/kobejayandy/article/details/13277035

2.http://www.cnblogs.com/peida/p/Guava_Cache.html

 

一.Guava简介:

1.Google Guava库是一个非常优秀的包含很多Java工具类集的库,使用Google Guava来编写优雅的代码

 

2.与现有的Apache Commons相比:同样出色,并且目前发展比Apache Commons系列更为迅速的Google Guava库。

3.内容:Guava本身是Google内部的核心Java基础库,其涵盖的内容包含集合、缓存、基础类型、并发处理、常用注解、字符串处理、I/O、网络、数学运算、反射、范围(Range)等方面。

4.为什么要使用Guava:Guava的开发活跃度和良好的质量保证是我更愿意转而使用Guava的的原因之一。Guava几年发展下来各界发表的各类文章和其自身良好的文档风格也极大的帮助了该库的传播使用
注:从上面的Stackoverflow的讨论来看,google的java开发主管带领的小组负责该库的主要维护工作


5.Guava相关文档和资源
首先推荐访问Guava的知识库和API文档
Guava官方网站也给出非常有用的学习资源的地址:
Presentation slides focusing on base, primitives, and io
Presentation slides focusing on cache
Presentation slides focusing on util.concurrent
A nice collection of other helpful links

6.使用Guava
如果你是使用Maven作为项目管理和集成工具的话,那么只需要拷贝下面一段代码到项目的pom.xml中即可。
<dependency>
     <groupId>com.google.guava</groupId>
     <artifactId>guava</artifactId>
     <version>14.0-rc3</version>
</dependency>

 

 

二.Guava cache

 

1.关于缓存

缓存:在我们日常开发中是必不可少的一种解决性能问题的方法。简单的说,cache 就是为了提升系统性能而开辟的一块内存空间。

主要作用:是暂时在内存中保存业务系统的数据处理结果,并且等待下次访问使用。在日常开发的很多场合,由于受限于硬盘IO的性能或者我们自身业务系统的数据处理和获取可能非常费时,当我们发现我们的系统这个数据请求量很大的时候,频繁的IO和频繁的逻辑处理会导致硬盘和CPU资源的瓶颈出现。缓存的作用就是将这些来自不易的数据保存在内存中,当有其他线程或者客户端需要查询相同的数据资源时,直接从缓存的内存块中返回数据,这样不但可以提高系统的响应时间,同时也可以节省对这些数据的处理流程的资源消耗,整体上来说,系统性能会有大大的提升。

缓存在很多系统和架构中都用广泛的应用,例如:
1.CPU缓存 2.操作系统缓存 3.本地缓存 4.分布式缓存 5.HTTP缓存 6.数据库缓存等等,
可以说在计算机和网络领域,缓存无处不在。可以这么说,只要有硬件性能不对等,涉及到网络传输的地方都会有缓存的身影。

 

2.Guava Cache

Guava Cache是一个全内存的本地缓存实现,它提供了线程安全的实现机制。整体上来说Guava cache 是本地缓存的不二之选,简单易用,性能好

 

3.Guava Cache有两种创建方式

第一个: cacheLoader
第二个: callable callback

这两种方法和通常用map来缓存的做法比
相同点:这两种方法都实现了一种逻辑——从缓存中取key-X的值,如果该值已经缓存过了,则返回缓存中的值,如果没有缓存过,可以通过某个方法来获取这个值:
不同点:

cacheloader 的定义比较宽泛,是针对整个cache定义的,可以认为是统一的根据key值loadvalue的方法。

callable 的方式较为灵活,允许你在get的时候指定

 

cacheLoader方式实现实例

 

GuavaCacheUtil.java
@Test
    public void TestLoadingCache() throws Exception{
        LoadingCache<String,String> cahceBuilder=CacheBuilder
        .newBuilder()
        .build(new CacheLoader<String, String>(){
            @Override
            public String load(String key) throws Exception {       
                String strProValue="hello "+key+"!";               
                return strProValue;
            }
           
        });       
       
        System.out.println("jerry value:"+cahceBuilder.apply("jerry"));
        System.out.println("jerry value:"+cahceBuilder.get("jerry"));
        System.out.println("peida value:"+cahceBuilder.get("peida"));
        System.out.println("peida value:"+cahceBuilder.apply("peida"));
        System.out.println("lisa value:"+cahceBuilder.apply("lisa"));
        cahceBuilder.put("harry", "ssdded");
        System.out.println("harry value:"+cahceBuilder.get("harry"));
    }

 
  
输出:
jerry value:hello jerry!
jerry value:hello jerry!
peida value:hello peida!
peida value:hello peida!
lisa value:hello lisa!
harry value:ssdded  
 
callable callback的实现:

 

 

GuavaCacheUtil.java
@Test
    public void testcallableCache()throws Exception{
        Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(1000).build(); 
        String resultVal = cache.get("jerry", new Callable<String>() { 
            public String call() { 
                String strProValue="hello "+"jerry"+"!";               
                return strProValue;
            } 
        }); 
        System.out.println("jerry value : " + resultVal);
       
        resultVal = cache.get("peida", new Callable<String>() { 
            public String call() { 
                String strProValue="hello "+"peida"+"!";               
                return strProValue;
            } 
        }); 
        System.out.println("peida value : " + resultVal); 
    }

 
输出:
jerry value : hello jerry!
peida value : hello peida!
 
Cache的参数说明
  回收的参数:
  1. 大小的设置:CacheBuilder.maximumSize(long)  CacheBuilder.weigher(Weigher)  CacheBuilder.maxumumWeigher(long)
  2. 时间:expireAfterAccess(long, TimeUnit) expireAfterWrite(long, TimeUnit)
  3. 引用:CacheBuilder.weakKeys() CacheBuilder.weakValues()  CacheBuilder.softValues()
  4. 明确的删除:invalidate(key)  invalidateAll(keys)  invalidateAll()
  5. 删除监听器:CacheBuilder.removalListener(RemovalListener)
  

  refresh机制:
  1. LoadingCache.refresh(K)  在生成新的value的时候,旧的value依然会被使用。
  2. CacheLoader.reload(K, V) 生成新的value过程中允许使用旧的value
  3. CacheBuilder.refreshAfterWrite(long, TimeUnit) 自动刷新cache


基于泛型的实现:
/**
     * 不需要延迟处理(泛型的方式封装)
     * @return
     */
    public  <K , V> LoadingCache<K , V> cached(CacheLoader<K , V> cacheLoader) {
          LoadingCache<K , V> cache = CacheBuilder
          .newBuilder()
          .maximumSize(2)
          .weakKeys()
          .softValues()
          .refreshAfterWrite(120, TimeUnit.SECONDS)
          .expireAfterWrite(10, TimeUnit.MINUTES)       
          .removalListener(new RemovalListener<K, V>(){
            @Override
            public void onRemoval(RemovalNotification<K, V> rn) {
                System.out.println(rn.getKey()+"被移除"); 
               
            }})
          .build(cacheLoader);
          return cache;
    }
   
    /**
     * 通过key获取value
     * 调用方式 commonCache.get(key) ; return String
     * @param key
     * @return
     * @throws Exception
     */
 
    public  LoadingCache<String , String> commonCache(final String key) throws Exception{
        LoadingCache<String , String> commonCache= cached(new CacheLoader<String , String>(){
                @Override
                public String load(String key) throws Exception {
                    return "hello "+key+"!";   
                }
          });
        return commonCache;
    }
   
    @Test
    public void testCache() throws Exception{
        LoadingCache<String , String> commonCache=commonCache("peida");
        System.out.println("peida:"+commonCache.get("peida"));
        commonCache.apply("harry");
        System.out.println("harry:"+commonCache.get("harry"));
        commonCache.apply("lisa");
        System.out.println("lisa:"+commonCache.get("lisa"));
    }
 
   
基于泛型的Callable Cache实现:
private static Cache<String, String> cacheFormCallable = null;

   
    /**
     * 对需要延迟处理的可以采用这个机制;(泛型的方式封装)
     * @param <K>
     * @param <V>
     * @param key
     * @param callable
     * @return V
     * @throws Exception
     */
    public static <K,V> Cache<K , V> callableCached() throws Exception {
          Cache<K, V> cache = CacheBuilder
          .newBuilder()
          .maximumSize(10000)
          .expireAfterWrite(10, TimeUnit.MINUTES)
          .build();
          return cache;
    }

   
    private String getCallableCache(final String userName) {
           try {
             //Callable只有在缓存值不存在时,才会调用
             return cacheFormCallable.get(userName, new Callable<String>() {
                @Override
                public String call() throws Exception {
                    System.out.println(userName+" from db");
                    return "hello "+userName+"!";
               }
              });
           } catch (ExecutionException e) {
              e.printStackTrace();
              return null;
            }
    }
   
    @Test
    public void testCallableCache() throws Exception{
         final String u1name = "peida";
         final String u2name = "jerry";
         final String u3name = "lisa";
         cacheFormCallable=callableCached();
         System.out.println("peida:"+getCallableCache(u1name));
         System.out.println("jerry:"+getCallableCache(u2name));
         System.out.println("lisa:"+getCallableCache(u3name));
         System.out.println("peida:"+getCallableCache(u1name));
        
    }
 
说明:Callable只有在缓存值不存在时,才会调用,比如第二次调用getCallableCache(u1name)直接返回缓存中的值

 

 


4.guava Cache数据移除

被动移除主动移除两种

 

被动移除数据的三种方式
1.基于大小的移除

理解:看字面意思就知道就是按照缓存的大小来移除,如果即将到达指定的大小,那就会把不常用的键值对从cache中移除。
定义的方式:

一般常用: CacheBuilder.maximumSize(long),

不常用的:还有一种一种可以算权重的方法,个人认为实际使用中不太用到。
就这个常用的来看有几个注意点,
(1) 这个size指的是cache中的条目数,不是内存大小或是其他;
(2) 并不是完全到了指定的size系统才开始移除不常用的数据的,而是接近这个size的时候系统就会开始做移除的动作
(3) 如果一个键值对已经从缓存中被移除了,你再次请求访问的时候,如果cachebuild是使用cacheloader方式的,那依然还是会从cacheloader中再取一次值,如果这样还没有,就会抛出异常
  
2.基于时间的移除

理解:guava提供了两个基于时间移除的方法

expireAfterAccess(long, TimeUnit)  

这个方法是根据某个键值对最后一次访问之后多少时间后移除

expireAfterWrite(long, TimeUnit)  

这个方法是根据某个键值对被创建或值被替换后多少时间移除
  
3.基于引用的移除
理解:这种移除方式主要是基于java的垃圾回收机制,根据键或者值的引用关系决定移除
  

主动移除数据方式,主动移除有三种方式
1.单独移除用 Cache.invalidate(key)
2.批量移除用 Cache.invalidateAll(keys)
3.移除所有用 Cache.invalidateAll()

 

如果需要在移除数据的时候有所动作还可以定义Removal Listener,但是有点需要注意的是默认Removal Listener中的行为是和移除动作同步执行的,如果需要改成异步形式,可以考虑使用RemovalListeners.asynchronous(RemovalListener, Executor)


方法对比:
get(K):这个方法要么返回已经缓存的值,要么使用CacheLoader向缓存原子地loading新值(就是上面说的当缓存没有值的时候执行Load方法)
put(key, value):这个方法可以直接显示地向缓存中插入值,这会直接覆盖掉已有键之前映射的值。

缓存回收:
CacheBuilder.maximumSize(long):这个方法规定缓存项的数目不超过固定值(其实你可以理解为一个Map的最大容量),尝试回收最近没有使用或总体上很少使用的缓存项

定时回收(Timed Eviction):
expireAfterAccess(long, TimeUnit):缓存项在给定时间内没有被读/写访问,则回收。请注意这种缓存的回收顺序和基于大小回收一样。
expireAfterWrite(long, TimeUnit):缓存项在给定时间内没有被写访问(创建或覆盖),则回收。如果认为缓存数据总是在固定时候后变得陈旧不可用,这种回收方式是可取的。














分享到:
评论

相关推荐

    Guava-Cache本地缓存案例代码

    Guava Cache是Google Guava库中的一个强大特性,它提供了高效的本地缓存解决方案,用于存储经常访问的数据,以减少对远程服务或计算的调用,从而提高应用性能。本案例代码将详细介绍Guava Cache的使用,包括缓存的...

    第七章 企业项目开发--本地缓存guava cache1

    【标题】:第七章 企业项目开发--本地缓存Guava Cache1 【描述】:在企业级项目开发中,缓存技术起着至关重要的作用,数据库设计往往也会考虑缓存策略。本地缓存和分布式缓存是常见的两种缓存方式,其中Guava Cache...

    guava-cache.rar

    Guava Cache是Google Guava库中的一个强大特性,它提供了高效的本地缓存解决方案。在许多应用程序中,我们经常需要缓存数据以减少不必要的数据库查询或远程服务调用,提高系统性能。尽管分布式缓存如Redis在高并发和...

    spring-boot-redis-guava-caffeine-cache:springboot 使用 redis guava caffeine 缓存示例

    在实际应用中,可以根据业务需求选择合适的缓存策略,例如Redis适用于分布式环境,而Guava Cache和Caffeine更适合本地缓存。 在实际操作中,项目可能包含以下部分: 1. 配置文件:`application.properties`或`...

    Go-Localcaching-GuavaCache在Go中的部分的实现

    然而,开发者可以借鉴Guava Cache的设计理念,使用Go的标准库或者其他第三方库来实现类似的本地缓存机制。`goburrow-cache-0d64ef4`这个压缩包可能就是一个这样的实现,它提供了Go中对Guava Cache功能的部分模仿。 ...

    使用google guava 实现定时缓存功能

    首先,Guava的Cache组件是其核心特性之一,它提供了一种高效、自动化的缓存机制。定时缓存功能允许我们存储计算结果或从远程服务获取的数据,并在预设的时间间隔后自动过期,以确保数据的时效性。这在处理频繁但计算...

    guava-21.0-rc2 、guava-21.0-rc2-javadoc 、guava-21.0-rc2-sources

    - **缓存**: `LoadingCache`的性能提升和更丰富的API,使得内存缓存的管理更加灵活。 - **字符串处理**: 提供了更多处理字符串的方法,如`Joiner`和`Splitter`,便于进行复杂的字符串操作。 - **错误处理**: 引入了`...

    Guava-Cache-Demo:演示如何使用 Guava 缓存

    总结来说,`Guava-Cache-Demo` 展示了如何利用 Guava Cache 实现高效的数据缓存,通过将 Google Books API 的调用结果缓存起来,减少了不必要的网络延迟,提高了应用程序的响应速度。通过定制缓存的过期策略、最大...

    springboot本地缓存(guava与caffeine).docx

    Spring Boot 本地缓存(Guava 与 Caffeine) Spring Boot 中的本地缓存是指在应用程序中存储和检索数据的机制...在 Spring Boot 中,我们可以使用 Guava 或 Caffeine 来实现本地缓存,提高应用程序的性能和响应速度。

    SpringBoot加入Guava Cache实现本地缓存代码实例

    SpringBoot 中 Guava Cache 的应用 在本文中,我们将介绍如何在 SpringBoot 项目中使用 Guava Cache 实现本地缓存。Guava Cache 是一个高性能的缓存框架,由 Google 开发维护。它提供了一个灵活的缓存机制,可以...

    DurianCoder#springboot-example#Springboot集成GuavaCache实现本地缓存1

    Springboot集成本地缓存Guava本章介绍一个比较好用的本地缓存Guava0x01、添加依赖0x02、添加GuavaLocalCache提供了设置超时时

    mahout的guava-r09-jar

    2. **缓存机制**:Guava的LoadingCache接口可以方便地创建自定义缓存策略,这对于频繁访问的数据,可以减少重复计算和提高响应速度。 3. **并发工具**:Guava提供了如CountDownLatch、CyclicBarrier等并发控制工具...

    Springboot整合GuavaCache缓存过程解析

    GuavaCache是Google开源的一款本地缓存机制,具有简单、强大、轻量级的特点。SpringBoot整合GuavaCache缓存过程解析是指使用SpringBoot框架将GuavaCache整合到应用程序中,以提高应用程序的性能和响应速度。 Guava...

    详解Guava Cache本地缓存在Spring Boot应用中的实践

    Guava Cache可以作为Spring Boot应用中的本地缓存,以提高程序的性能。在使用Guava Cache之前,需要在pom.xml文件中添加相应的依赖,包括Spring Boot、MyBatis、MySQL和Guava Cache等。在配置Guava Cache时,需要...

    本地缓存与分布式缓存优缺点,使用

    3. 缓存系统作为 ORM 框架的二级缓存对外提供服务,减轻数据库的负载压力,加速应用访问并行处理,涉及大量中间计算结果需要共享等等。 分布式缓存 1. Redis。 2. Memcache。 本地缓存和分布式缓存都是缓存技术中...

    cache-api-1.0.0.jar

    总的来说,“cache-api-1.0.0.jar”是一个遵循JSR107规范的缓存API实现,它的存在简化了Java应用程序中缓存的集成和管理。通过使用这个API,开发者可以享受到标准缓存接口带来的便捷性,同时保证了与不同缓存实现的...

    如何基于LoadingCache实现Java本地缓存

    LoadingCache 是 Guava 库提供的一种缓存实现方式,本文将详细介绍如何基于 LoadingCache 实现 Java 本地缓存。 一、Guava 介绍 Guava 是 Google 开源的一套工具库,其中提供的 cache 模块非常方便,是一种与 ...

    spring-cache-demo:spring整合guava和redis实现本地和远程缓存

    在这个名为“spring-cache-demo”的项目中,我们看到它整合了Guava Cache和Redis,实现了本地和远程缓存的功能。 首先,让我们来深入理解Spring Cache。Spring Cache允许开发者在不修改业务代码的情况下,通过简单...

    redis本地缓存与redis缓存

    文件名称“RedisCache-master”可能是一个包含Redis缓存相关项目的源代码仓库,里面可能包括了如何配置、使用Redis作为缓存的示例代码,以及如何与本地缓存结合的实践。 总结来说,本地缓存和Redis缓存各有优势,...

    Guava-CacheDemo.rar

    Guava Cache广泛应用于各种场景,如Web应用的session缓存、API请求的本地缓存、数据库查询结果缓存等。通过合理配置和设计,可以有效提升系统性能,减少不必要的计算和网络延迟。 总结,Guava Cache是一个强大的...

Global site tag (gtag.js) - Google Analytics