CacheBuilder.newBuilder() 使用cache机制

cache用来比如对于同样一次输入不止一次的取值的时候,使用缓存。

公司使用cache进行缓存token,时效一天,但是经常过期,找不到原因,故来学习一下缓存机制。

使用的是guava本地缓存,并没有使用redis作为缓存机制

公司使用的是

package com.google.common.cache;

来进行的缓存
我的怀疑是 1.有可能是cache的池的大小负载过了
2.可能是定时任务的锅 更新的时候把以前的缓存搞丢了

引用的maven依赖,使用的是guava缓存机制
 

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>11.0.2</version>
</dependency>

 

 

1.cache中的softValues()是什么意思

softValues()方法,这样map中的value值都包裹在一个SoftReference(软引用)对象中,可以在内存过低的时候被当作垃圾回收。

所以这个在我们的cache机制中没有进行添加使用

Guava Cache缓存机制有两个基本的接口:Cache和LoadingCache,LoadingCache接口继承自Cache接口。

Cache

Cache接口提供了键和值的映射,但是Cache接口中提供的一些方法比HashMap提供的更基本。使用maps或caches的传统做法是:我们提供一个key,如果缓存中存在key对应的value值,我们就将这个value值返回,否则的话,如果通过相应的key找到映射关系,就返回null 值,为了在缓存中设置value值,我们可能需要这样做:

put(key,value);

我们需要明确的在cache或map中关联key和value,Cache使用了传统的put方法设置value值,但是获取value的时候,Guava Cache有自己的调用风格,如下:

V value = cache.get(key, Callable<? Extends V> value);

上面的方法会检索当前的value值,如果值不存在的话会从Callback实例中提取value值,通过key关联value,并返回相应的value值,它为我们提供了通过调用一个方法来替代下面风格的编程:

value = cache.get(key);
 
if(value == null){
 
    value =someService.retrieveValue();
 
    cache.put(key,value);
 
}

//也就是说没有得到get对应的value值,那么通过callback来进行添加相应的key和value
 

spring中bean的scope属性,有如下5种类型:

  1. singleton 表示在spring容器中的单例,通过spring容器获得该bean时总是返回唯一的实例
  2. prototype表示每次获得bean都会生成一个新的对象
  3. request表示在一次http请求内有效(只适用于web应用)
  4. session表示在一个用户会话内有效(只适用于web应用)
  5. globalSession表示在全局会话内有效(只适用于web应用)

2. refresh和expire刷新机制

刷新机制:包括refresh和expire刷新机制

expireAfterAccess: 当缓存项在指定的时间段内没有被读或写就会被回收。

expireAfterWrite:当缓存项在指定的时间段内没有更新就会被回收。

refreshAfterWrite:当缓存项上一次更新操作之后的多久会被刷新。

   考虑到时效性,我们可以使用expireAfterWrite,使每次更新之后的指定时间让缓存失效,然后重新加载缓存。guava cache会严格限制只有1个加载操作,这样会很好地防止缓存失效的瞬间大量请求穿透到后端引起雪崩效应。
     然而,通过分析源码,guava cache在限制只有1个加载操作时进行加锁,其他请求必须阻塞等待这个加载操作完成;而且,在加载完成之后,其他请求的线程会逐一获得锁,去判断是否已被加载完成,每个线程必须轮流地走一个“”获得锁,获得值,释放锁“”的过程,这样性能会有一些损耗。这里由于我们计划本地缓存1秒,所以频繁的过期和加载,锁等待等过程会让性能有较大的损耗。

     因此我们考虑使用refreshAfterWrite。refreshAfterWrite的特点是,在refresh的过程中,严格限制只有1个重新加载操作,而其他查询先返回旧值,这样有效地可以减少等待和锁争用,所以refreshAfterWrite会比expireAfterWrite性能好。但是它也有一个缺点,因为到达指定时间后,它不能严格保证所有的查询都获取到新值。了解过guava cache的定时失效(或刷新)原来的同学都知道,guava cache并没使用额外的线程去做定时清理和加载的功能,而是依赖于查询请求。在查询的时候去比对上次更新的时间,如超过指定时间则进行加载或刷新。所以,如果使用refreshAfterWrite,在吞吐量很低的情况下,如很长一段时间内没有查询之后,发生的查询有可能会得到一个旧值(这个旧值可能来自于很长时间之前),这将会引发问题。
--------------------- 
作者:Shiftyman 
原文:https://blog.csdn.net/abc86319253/article/details/53020432 

//感觉讲得很好

  • 5
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
CacheBuilder.newBuilder是Google Guava库中的一个方法,用于创建一个新的CacheBuilder实例。CacheBuilder是构建缓存的构建器,它提供了许多配置选项来自定义缓存的行为。使用CacheBuilder.newBuilder()方法可以创建一个默认的CacheBuilder实例,然后可以使用该实例上的其他方法来进行进一步的配置和构建。 例如,可以使用maximumSize方法设置缓存的最大容量,可以使用expireAfterAccess或expireAfterWrite方法设置缓存项的过期时间,可以使用removalListener方法设置缓存项被移除时的回调函数等等。 在引用中的代码示例中,CacheBuilder.newBuilder()方法被用于创建一个CacheBuilder实例,并在构建时通过链式调用方法设置了maximumSize选项。 注意,引用中提到的asMap视图上的方法不会自动加载缓存项,因此在需要自动加载缓存项的情况下,应该优先使用Cache.get(K, Callable<V>)方法,而不是Cache.asMap().putIfAbsent方法。 引用提到了Cache和LoadingCache接口,Cache是缓存的基本接口,LoadingCache是继承自Cache接口的接口,用于支持自动加载缓存项的缓存。在使用CacheBuilder.newBuilder()方法创建CacheBuilder实例时,可以通过build方法传入一个CacheLoader实例来实现自动加载缓存项的功能。 总之,CacheBuilder.newBuilder()方法是Google Guava库中用于创建CacheBuilder实例的方法,通过该实例可以进行缓存的配置和构建。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值