Caffeine cache实现本地缓存题

  • 缓存填充策略
    •  手动加载
      •  介绍:
      •  使用方式:
    •  同步加载
      •  介绍:
      •  使用方式:
    •  异步加载
      •  介绍:
      •   注意: 异步和同步使用方式相似, 这里的话主要写一下创建和异步转同步
      •  使用方式:
  • 过期策略
    •  基于大小过期
      •   介绍:当缓存超出后,使用W-TinyLFU算法进行缓存淘汰处理
      •   使用方式:
    •  基于权重过期
      •   介绍:
      •   使用方式:
    •  基于时间过期
      •   介绍:
      •   使用方式:
    •  基于引用回收
      •   介绍:
      •   使用方式:
  • 基本使用
    •  手动删除
      •   使用方式:
    •  自动刷新
      •   使用方式:
    •  移除通知
      •   使用方式:
    •  外部存储
      •   使用方式:
    •  统计缓存使用情况
      •   使用方式:
  • 实例整合
    •  编码方式
      •   使用方式:
    •  注解方式(整合SpringBoot的cache)
      •   介绍:
      •   使用方式:
        •    @Cacheable注解:
        •    @CachePut注解:
        •    @CacheEvict注解:
        •    @CacheConfig注解:
        •    @Caching注解:
  • 简易缓存工具类

缓存填充策略

介绍:缓存的填充方式有三种,手动、同步和异步

 手动加载

 介绍:

手动控制缓存的增删改处理,主动增加、获取以及依据函数式更新缓存,底层使用ConcurrentHashMap进行节点存储,因此get方法是安全的。批量查找可以使getAllPresent()方法或者带填充默认值的getAll()方法

 使用方式:

@Test
void test1() {com.github.benmanes.caffeine.cache.@NonNull Cache<String, String> cache = Caffeine.newBuilder()// 最大数量.maximumSize(100)// 设置缓存策略在1天未写入过期缓存.expireAfterAccess(1, TimeUnit.DAYS).build();// 存入缓存cache.put("cl", "cl");// 根据键值获取缓存System.out.println(cache.getIfPresent("cl"));// 根据键值获取缓存, 如果为空则调用后面的参是System.out.println(cache.get("abc", this::buildLoader));// 根据键值清除缓存cache.invalidate("abc");System.out.println(cache.getIfPresent("abc"));
}
// 缓存后面执行的方法String buildLoader(String k) {return k + "+default";
}

 同步加载

 介绍:

LoadingCache对象进行缓存的操作,使用CacheLoader进行缓存存储管理。 批量查找可以使用getAll()方法。 默认情况下, getAll()将会对缓存中没有值的key分别调用CacheLoader.load方法来构建缓存的值(build中的表达式)。我们可以重写CacheLoader.loadAll方法来提高getAll()的效率。

 使用方式:

@Test
void test1() {LoadingCache<String, String> loadingCache = Caffeine.newBuilder().maximumSize(100).expireAfterAccess(1, TimeUnit.DAYS)// getAll将会对缓存中, 没有值的key分别调用CacheLoader.load方法来构建缓存的值.build(this :: buildLoader);// 存储要添加的缓存List<String> keys = new ArrayList<>();keys.add("cl");keys.add("b");keys.add("c");keys.add("d");// 返回一个mapMap<String, String> cacheAll = loadingCache.getAll(keys);System.out.println(cacheAll.get("b"));System.out.println(cacheAll.get("c"));System.out.println(cacheAll.get("a"));
}
// 缓存后面执行的方法String buildLoader(String k) {return k + "+default";
}

 异步加载

 介绍:

AsyncLoadingCache对象进行缓存管理,get()返回一个CompletableFuture对象,默认使用ForkJoinPool.commonPool()来执行异步线程,但是我们可以通过Caffeine.executor(Executor) 方法来替换线程池

  注意: 异步和同步使用方式相似, 这里的话主要写一下创建和异步转同步

 使用方式:

@Test
void test1() {AsyncLoadingCache<String, String> asyncLoadingCache = Caffeine.newBuilder().maximumSize(100).expireAfterAccess(1,TimeUnit.DAYS).buildAsync(k-> this.buildLoaderAsync(k).get());try {System.out.println(asyncLoadingCache.get("123").get());} catch (Exception e) {e.printStackTrace();}
}
// 类似同步的load
CompletableFuture<String> buildLoaderAsync(String k) {return CompletableFuture.supplyAsync(() -> k + "buildLoaderAsync");
}
转换使用方式:
AsyncLoadingCache<String, String> asyncLoadingCache = Caffeine.newBuilder().maximumSize(100).expireAfterAccess(1,TimeUnit.DAYS).buildAsync(k -> this.buildLoaderAsync(k).get());
// 异步转同步
LoadingCache<String, String> cache = asyncLoadingCache.synchronous();
System.out.println("------------");
System.out.println(cache.get("dd"));

过期策略

介绍:

Caffeine的缓存清除是惰性的,可能发生在读请求后或者写请求后
比如说有一条数据过期后,不会立即删除,可能在下一次读/写操作后触发删除(类比于redis的惰性删除)。
如果读请求和写请求比较少,但想要尽快的删掉cache中过期的数据的话,
可以通过增加定时器的方法,定时执行cache.cleanUp()方法(异步方法,可以等待执行),触发缓存清除操作。

 基于大小过期

  介绍:当缓存超出后,使用W-TinyLFU算法进行缓存淘汰处理

  使用方式:

  maximumSize()方法,参数是缓存中存储的最大缓存条目,当添加缓存时达到条目阈值后,将进行缓存淘汰操作// 使用方式 AsyncLoadingCache<String, String> asyncLoadingCache = Caffeine.newBuilder().maximumSize(100)

 基于权重过期

  介绍:

通过权重来计算,每个实体都有不同的权重,总权重到达最高时淘汰实体。
weigher()方法可以指定缓存所占比重,maximumWeight()方法指定最大的权重阈值,当添加缓存超过规定权重后,进行数据淘汰

  使用方式:

com.github.benmanes.caffeine.cache.@NonNull LoadingCache<String, String> cache = Caffeine.newBuilder().maximumWeight(10).weigher(new Weigher<Object, Object>() {@Overridepublic @NonNegative int weigh(@NonNull Object o, @NonNull Object o2) {System.out.println("key" + o + "value" + o2);return 5;}}).build(this::buildLoader);
List<String> list = Lists.newArrayList("c1", "c2", "c3");
cache.put(list.get(0), list.get(0));
System.out.println(list.get(0) + "--" + cache.get(list.get(0)));
cache.put(list.get(1), list.get(1));
System.out.println(list.get(1) + "---" + cache.get(list.get(1)));
System.out.println(cache.getAll(list));

 基于时间过期

  介绍:

expireAfterAccess():缓存访问后,一定时间失效;即最后一次访问或者写入开始时计时。
expireAfterWrite():缓存写入后,一定时间失效;以写入缓存操作为准计时。(在最后一次写入缓存后开始计时,在指定的时间后过期。)
expireAfter():自定义缓存策略,满足多样化的过期时间要求。
这里只展示after, 其他的话 使用方式大致相同,自己动手试试
注意:当expireAfterAccess和expireAfterWrite同时存在时,只有expireAfterWrite有效

  使用方式:

com.github.benmanes.caffeine.cache.@NonNull LoadingCache<String, String> cache = Caffeine.newBuilder().expireAfter(new Expiry<Object, Object>() {// 创建后过期@Overridepublic long expireAfterCreate(@NonNull Object o, @NonNull Object o2, long l) {return 1;}// 更新后过期@Overridepublic long expireAfterUpdate(@NonNull Object o, @NonNull Object o2, long l, @NonNegative long l1) {return 1;}// 读取后过期@Overridepublic long expireAfterRead(@NonNull Object o, @NonNull Object o2, long l, @NonNegative long l1) {return 1;}}).build(this::buildLoader);

 基于引用回收

  介绍:

  使用方式:

基本使用

 手动删除

  使用方式:

 自动刷新

  使用方式:

refreshAfterWrite:这里设置的是1分钟后自动刷新

 移除通知

  使用方式:

 外部存储

  使用方式:



 统计缓存使用情况

  使用方式:

实例整合

 编码方式

  使用方式:

1、缓存配置类

@Configuration
public class CacheConfig {@Beanpublic Cache<String, Object> caffeineCache() {return Caffeine.newBuilder()// 设置最后一次写入或访问后经过固定时间过期.expireAfterWrite(60, TimeUnit.SECONDS)// 初始的缓存空间大小.initialCapacity(100)// 缓存的最大条数.maximumSize(1000).build();}
}

2、使用
注意:这里我只写了存入的写法, 如果要获取缓存,用cache的get缓存我们存储的key就可以了。
如:

// 以下代码的具体含义请看文章, 文章都有介绍,如果没有 可以评论 我会给你进行解答
cache.put(1,"测试缓存")
// 获取缓存
cache.get("1");
// 如果你使用get爆红, 那可能是因为你没有填写第二个,那么你可以这样做
cache.get("1", value -> value);
// 或者
cache.asMap().get("1");

示例:

private final Cache<Object, Object> cache;
public FeedbackServiceImpl( Cache<Object, Object>  cache) {this.cache = cache;
}
public void insertFeedBack(Feedback feedback) {int i = feedbackMapper.insert(feedback);cache.put(feedback.getId(), feedback);
}

注意:如果你只是简单的使用, 你可以使用末文的缓存工具类

 注解方式(整合SpringBoot的cache)

  介绍:


  使用方式:

   @Cacheable注解:

   @CachePut注解:

   @CacheEvict注解:

   @CacheConfig注解:
// 一个类中可能会有多个缓存操作,而这些缓存操作可能是重复的。这个时候可以使用
@CacheConfig(cacheNames="emp") //抽取缓存的公共配置
   @Caching注解:

示例:

// 开启缓存
@EnableCaching
public class Springboot01CacheApplication {public static void main(String[] args) {SpringApplication.run(Springboot01CacheApplication.class, args);}
}// 其他方法使用和他一样, 具体可以看代码,来自己动动手试试看@Cacheable(cacheNames = {"emp"},condition = "#id>0")public Employee getEmp(Integer id){System.out.println("查询"+id+"号员工");Employee emp = employeeMapper.getEmpById(id);return emp;}

简易缓存工具类

 具体含义看代码注释

/*** @author huangye  所谓致知在格物者,言欲致吾之知,在即物而穷其理也。* @version 1.0  2020/10/4*/
public class CacheUtil{private static  Cache<String, Object> cache;static {cache = createCache();}/*** 插入缓存 | 更新缓存* @param cacheName 缓存前缀* @param key 键* @param value 值*/public static void saveCache(String cacheName, String key, Object value) {System.out.printf("存储缓存的数据 key(%s) value(%s)",cacheName + "-" + key, value);System.out.println();cache.asMap().put(cacheName + "-" + key, value);}/*** 根据键获取缓存* @param cacheName 缓存前缀* @param key 键* @return Object类型, 由使用者自己转换*/public static Object getCache(String cacheName, String key) {System.out.printf("获取缓存的数据 key(%s) value(%s)",cacheName + "-" + key,cache.asMap().get(cacheName + "-" + key) );System.out.println();return cache.asMap().get(cacheName + "-" + key);}/*** 根据键值删除缓存* @param cacheName 缓存前缀* @param key 建*/public static void deleteCache(String cacheName, String key) {System.out.printf("删除缓存的数据 key(%s)", cacheName + "-" + key);System.out.println();cache.asMap().remove(cacheName + "-" + key);}private static class CacheSingletonHolder {private final static Cache<String, Object> CACHE = Caffeine.newBuilder()// 初始的缓存空间大小.initialCapacity(100)// 缓存的最大条数.maximumSize(1000)// 最后一次缓存访问过后,7天后失效.expireAfterAccess(7, TimeUnit.DAYS).build();}private static Cache<String, Object> createCache() {return CacheSingletonHolder.CACHE;}
}

ps:这里的图片都来源于我学习时做的笔记(下图位证), 因为有的是在网上找文章学习的,所以可能会遇到有的是和别人一样的内容,我是想着吧那些之前看的文章放到文章末尾的,但是我找不到了非常抱歉, 我这里的话只是想做个知识的汇总,如果有错误的地方,可以评论留言 我会改正,谢谢

Caffeine cache实现本地缓存(简单又清楚)相关推荐

  1. 干掉 GuavaCache:Caffeine 才是本地缓存的王

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 话说,中间件的选择上,Spring(SpringBoot ...

  2. ehcache缓存原理_干掉GuavaCache:Caffeine才是本地缓存的王

    话说,中间件的选择上,Spring(SpringBoot)一直是业界的风向标.比如Spring一直使用「Jackson」,而没有使用Gson和fastjson.SpringBoot2.0默认数据库连接 ...

  3. 干掉GuavaCache:Caffeine才是本地缓存的王

    点击上方"朱小厮的博客",选择"设为星标" 后台回复"加群",加入新技术 话说,中间件的选择上,Spring(SpringBoot)一直是业 ...

  4. guava_使用Google Guava Cache进行本地缓存

    guava 很多时候,我们将不得不从数据库或另一个Web服务获取数据或从文件系统加载数据. 在涉及网络呼叫的情况下,将存在固有的网络延迟,网络带宽限制. 解决此问题的方法之一是在应用程序本地拥有一个缓 ...

  5. 使用Google Guava Cache进行本地缓存

    很多时候,我们将不得不从数据库或另一个Web服务获取数据或从文件系统加载数据. 在涉及网络呼叫的情况下,将存在固有的网络等待时间,网络带宽限制. 解决此问题的方法之一是在应用程序本地拥有一个缓存. 如 ...

  6. java 自动过期缓存_Java自动过期本地缓存简单实现

    实际项目中常常需要用到本地缓存,特别是一些固定不变的数据,不想频繁调接口,因为http请求本身需要耗时,下面几个类对本地缓存作了简单实现,支持自动过期功能 LocalCache.javainterfa ...

  7. java guava cache_java使用guava cache实现本地缓存

    cache = CacheBuilder.newBuilder() .recordStats() .maximumSize(5000000) .expireAfterWrite(1, TimeUnit ...

  8. Google Guava Cache高效本地缓存

    目录 Guava Cache使用需求和场景 需求 场景 缓存设置 缓存的并发级别 缓存的初始容量设置 设置最大存储 缓存清除策略 基于存活时间的清除策略 基于容量的清除策略 基于权重的清除 策略 显式 ...

  9. Java高性能本地缓存框架Caffeine

    文章目录 Java高性能本地缓存框架Caffeine 如何使用 缓存加载 手动加载 自动加载 手动异步加载 自动异步加载 过期策略 基于大小 基于时间 基于引用 Caffeine.weakKeys() ...

最新文章

  1. 每个设计师应该阅读的8本书
  2. 关于iOS去除数组中重复数据的几种方法
  3. python 内置函数 eval()函数 (用来执行一个字符串表达式,并返回表达式的值)
  4. 【转】Luajit-2.1.0-beta1的发布和生成arm64用bytecode的解脱
  5. URAL 1682 Crazy Professor (并查集)
  6. 临床必备 | 第 5 期全基因组/外显子组家系分析理论和实战
  7. 改善深层神经网络:超参数调整、正则化以及优化——2.8 Adam算法(Adaptive Moment Estimation)
  8. 【Ubuntu引导】EFI系统分区.删除不掉,也不能格式化,如何粘力删除 efi 隐藏分区
  9. 【操作系统/OS笔记17】文件系统基本概念、文件描述符、文件系统访问、文件别名、文件系统种类
  10. PowerDesigner一些小技巧
  11. JavaScript 盖尔-沙普利算法
  12. 【图像压缩】基于matlab GUI DCT图像压缩【含Matlab源码 842期】
  13. 关于笔记本测试的面试准备 2021-10-11
  14. 计算机科学与技术的学士服是什么颜色的,学士服颜色分类 各色学士服都有什么讲究...
  15. 庆祝北大“如何制作MOOC”课程取得优秀成绩
  16. 错误提示Incompatible file format错误原因和解决方案
  17. 测试人员,如何对直播类产品的直播质量进行测试呢?
  18. js做个随机点名的小游戏
  19. python如何在图片上写字
  20. Jieyue捷阅网购物商城项目介绍说明

热门文章

  1. Fragment和Activity两种沉浸式状态栏的实现
  2. 实战 | 用Python和MediaPipe搭建一个嗜睡检测系统 (详细步骤 + 源码)
  3. inventor2019有无CAE_autodeskinventor2019-独木成林
  4. 江汉大学计算机专业男女比,2018全国高校男女比例排行榜出炉!哪所大学最难找对象?...
  5. 建立在互联网上的公益金字塔
  6. 黄瓜西红柿为何不能同吃?(图)
  7. 11万字AI赋能智慧水利模型训练平台建设方案
  8. 精灵图的使用以及css其他效果运用
  9. 什么是spring?spring组成模块、spring优缺点、应用场景、bean的生命周期、线程并发问题
  10. 【SRIO】1、RapidIO协议概述