GuavaCache本地缓存(LoadingCache)的使用分析

添加mavne依赖

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>29.0-jre</version>
</dependency>

测试代码及注释

package com.swkj.customer.restapi.test;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/**
 * @Description:
 * @Author: GE LIANG
 * @Date: 2022/8/26 9:33
 */
public class CacheTest {
    private static LoadingCache<String, Object> loadingCache = CacheBuilder.newBuilder()
            // 并发级别
            .concurrencyLevel(8)
            // 初始容量
            .initialCapacity(10)
            // 超出阈值之后使用LRU算法溢出缓存项,只会在写入操作时候同步移除
            .maximumSize(100)
            // 缓存项自动定时刷新-》缓存项只有在被检索时才会真正刷新,即只有刷新间隔时间到了你再去get(key)才会重新去执行Loading否则就算刷新间隔时间到了也不会执行loading操作
            .refreshAfterWrite(3, TimeUnit.MINUTES)
            .build(new CacheLoader<String, Object>() {
                @Override
                public String load(String key) throws Exception {
                    /**
                     * 不同缓存数据要使用不同loadingCache获取
                     */

                    /**
                     * 方式1-单个插入缓存
                     */
                    // 回源操作(当通过get(key)的方式不存在的时候出发)
                    String result = "需要缓存的单条数据(可以是任何类型)";
                    return result;

                    /**
                     * 方式2-批量插入缓存
                     */
//                    Map<String, Object> batchCacheMap = new HashMap<>();
//                    batchCacheMap.put("key1", "abc123");
//                    batchCacheMap.put("key2", "模拟数据-需要获取的时候使用loadingCache.get(\"key2\")即可");
//                    loadingCache.putAll(batchCacheMap);
//                    return batchCacheMap.get(key);
                }
            });

    public static void main(String[] args) throws ExecutionException {
        /**
         * 方式一的获取方式
         */
        loadingCache.get("resultKey");

        /**
         * 方式二的获取方式
         */
//        loadingCache.get("key1");
//        loadingCache.get("key2");
    }
}

GuavaCache为开发人员提供了三种缓存被动更新机制,如下所示:

  • expireAfterAccess:缓存项在单位时间内未发生过读/写操作即被回收;
  • expireAfterWrite:缓存项在单位时间内未被更新即被回收;
  • refreshAfterWrite:缓存项离上一次更新操作多久之后会被更新;

expireAfterWrite机制:当缓存项过期触发回源操作时,GuavaCache会通过重入锁ReentrantLock严格地控制单机只能有一个线程在执行操作,而其他线程则必须阻塞等待直至回源操作完成,不过当回源操作结束后,之前那些被阻塞的线程仍然会逐一获取锁来验证回源结果;也就是说,每个线程必须轮流地经历取锁、取值,以及释放锁的过程,这样会存在一定程度上的性能损耗,适用缓存数据强一致性的场景

refreshAfterWrite机制:可以有效避免expireAfterWrite 机制在并发环境下因为锁资源竞争所带来的性能损耗,同expireAfterWrite类似,在执行回源操作时,单机仍然只允许一个线程在执行操作,但其他线程并不会阻塞,而是直接返回旧值;这么做虽然可以提升性能,但却仍然存在一个明显的问题,那就是refreshAfterWrite机制并不能够严格地确保返回值都是新值,适用缓存数据可以容忍短暂时间不一致场景

当然具体应该使用哪一种缓存被动更新机制,则还需要结合具体的业务场景而定。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

迪八戈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值