一、使用背景

在开发中经常用到缓存,首先想到的是redis,但是我们只想缓存少量的数据,并且只是给代码内部使用。redis固然好用,但是每次练级也是需要网络io的,所以本地缓存使用就有必要了。

二、用过的本地缓存:

刚开始了解到guava cache可以作为本地缓存,但是了解到caffeine性能更优于guava cache,而且springboot2.0开始不再支持guava cache了,而是用了caffeine代替。

一张图说明问题:

使用的场景:

1、经常需要查询的少量数据时,比如一些保存在数据库的配置信息使用频繁,可以考虑使用缓存,直接在内存读取,不需要每次查询数据库,减少网络io;

2、调用第三方接口存在重复返回相同结果的时候,如调用高德的逆地理查询接口,由于限制次数,而且存在相同的参数返回结果是一样的,使用缓存减少调用三方接口次数;

当然还有其他情况使用缓存,可以根据实际问题,具体考虑使用。要注意使用的时候过期key的处理问题,防止存储的数据量过大。只做缓存,不当数据库使用

三、怎么定义

不多说,先看看怎么在项目中使用。本次基于springboot使用caffeine

pom引入:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId>
</dependency>

代码如下:

package com.rxd.vhg.vehicledt.caffeine;import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.Scheduler;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.ArrayList;
import java.util.List;/*** @Title: CaffeineCacheConfig* @Description:* @Auther:* @Version: 1.0* @create */
@Configuration
@EnableCaching
public class CaffeineCacheConfig {@Beanpublic CacheManager caffeineCacheManager() {SimpleCacheManager cacheManager = new SimpleCacheManager();List<CaffeineCache> caffeineCaches = new ArrayList<>();for (CacheType cacheType : CacheType.values()) {caffeineCaches.add(new CaffeineCache(cacheType.name(),Caffeine.newBuilder().scheduler(Scheduler.systemScheduler()).expireAfterWrite(cacheType.getExpires(), cacheType.getUnit()).build()));}cacheManager.setCaches(caffeineCaches);return cacheManager;}@Beanpublic CacheLoader<Object, Object> cacheLoader() {return new CacheLoader<Object, Object>() {@Overridepublic Object load(Object key) throws Exception { return null;}// 重写这个方法将oldValue值返回回去,进而刷新缓存@Overridepublic Object reload(Object key, Object oldValue) throws Exception {System.out.println("--refresh--:"+key);return oldValue;}};}
}

缓存配置类:

package com.rxd.vhg.vehicledt.caffeine;import java.util.concurrent.TimeUnit;/*** @Title: CacheType* @Description:* @Auther:* @Version: 1.0* @create */
public enum CacheType {//BaseInfo 缓存24小时BASE_INFO(24,TimeUnit.HOURS),//alarmMonitor 缓存4小时ALARM_MONITOR(4,TimeUnit.HOURS),//gps 缓存10分钟GPS_INFO(1,TimeUnit.MINUTES);private int expires;private TimeUnit unit;CacheType(int expires,TimeUnit unit) {this.expires = expires;this.unit = unit;}public int getExpires() {return expires;}public TimeUnit getUnit(){return unit;}}

使用枚举类定义多个缓存,定义缓存名称、缓存时间、时间单位信息。

了解到的其他配置信息:

1)过期策略:基于大小:maximumSize:最大缓存数量;maximumWeight最大权重。两者不可同时出现

------> Caffeine.newBuilder().maximumSize(1000).build()

基于时间:expireAfterAccess :在最后一次访问或者写入后开始计时,即在最后一次读写后,经过多少时间才过期,如果一直在访问,则不会过期

------->Caffeine.newBuilder().expireAfterAccess (4,TimeUnit.HOURS).build()

expireAfterWrite:在最后一次写入缓存后开始计时,即在写入后经过固定的时间一定会过期。

------->Caffeine.newBuilder().expireAfterAccess (4,TimeUnit.HOURS).build()

expireAfter ------->自定义过期时间,没有使用过

四、怎么使用

springboot提供了注解使用缓存:@Cacheable、@CachePut、@CacheEvict

@Cacheable:先查询缓存是否存在,如果存在,则返回结果;如果不存在,则执行方法,并将结果保存在缓存中。主要用于查询操作

@CachePut:不检查缓存中是否存在,直接执行方法,并将结果保存在缓存中。主要用于数据新增和修改操作

@CacheEvict:从缓存中移除指定的key数据,如果allEntries属性为true,则清除全部;如果beforeInvocation属性为true,则在方法执行前删除。主要用于删除操作

@Cacheable(cacheNames = "BASE_INFO",key = "#root.methodName")
public List<String> region() {return this.baseMapper.getRegion();
}
@Cacheable(cacheNames = "GPS_INFO",key = "#lat")
public String getGpsInfo(String lat, String lng){return "ces" ;
}
@Cacheable(cacheNames = "GPS_INFO",key = "#lat+'-'+#lng")
public String getGpsInfo(String lat, String lng){return "ceshi";
}
@CacheEvict(value = "ALARM_MONITOR",allEntries = true,beforeInvocation = true)
public boolean cacheClearn() {return true;
}

说明:cacheNames 缓存名称;key 缓存中唯一键,支持SPEL表达式,无参数时,可以考虑使用方法名称作为key、单个值为key、多个值为key

注意点:执行缓存的不能同一个类中调用,固然缓存中时存在数据,也依然会执行方法(这种情况跟异步注解类似,同一个类中调用无效)

五、使用扩展

一般是将注解放在service实现的方法上,但是注解也是可以使用在mapper方法中、或者FeignClient方法中(就是在interface上使用),注意此时的key的使用

@FeignClient("rxd-biz-base-info")
public interface BaseInfoFeign {/*** 设置本地缓存4小时有效,vin为key(p2表示vin的值),*/@GetMapping("/api/vehicle/")@Cacheable(cacheNames = "ALARM_MONITOR",key = "#p2")BaseResult<List<WorkOrder>> getVehicle(@RequestParam("pageNum")Integer pageNum, @RequestParam("pageSize")Integer pageSize, @RequestParam("vin")String vin);
}

具体原因请见:https://blog.csdn.net/f641385712/article/details/95169002

六、过期key清除

Caffeine 不会在key过期后立即执行清除,而是在写入或者读取操作之后执行少量维护工作,或者在写入读取很少的情况下,偶尔执行清除操作。

如果我们项目写入或者读取频率很高,那么不用担心。如果想入写入和读取操作频率较低,那么我们可以通过Cache.cleanUp() 加scheduler 去定时执行清除操作。

可以使用Scheduler.systemScheduler()来完成

Caffeine.newBuilder().scheduler(Scheduler.systemScheduler()).build()

【学习总结】项目中用到的caffeine缓存相关推荐

  1. iOS 项目中用到的一些开源库和第三方组件

    iOS 项目中用到的一些 iOS 开源库和第三方组件 分享一下我目前所在公司 iOS 项目中用到的一些 iOS 开源库和第三方组件, 感谢开源, 减少了我们的劳动力, 节约了我们大量的时间, 让我们有 ...

  2. 在.Net项目中使用Redis作为缓存服务

    最近由于项目需要,在系统缓存服务部分上了redis,终于有机会在实际开发中玩一下,之前都是自己随便看看写写,很零碎也没沉淀下来什么,这次算是一个系统学习和实践过程的总结. 和Redis有关的基础知识 ...

  3. 如何学习开源项目及Ceph的浅析

    摘要:开源技术的学习和采用确实存在着一定门槛,然而学习各种开源项目已经成为许多开发者不可回避的工作内容.那么,对于类似OpenStack的大型开源项目,开发者该如何着手,这里我们看章宇的分享. [编者 ...

  4. android图片缓存,直接应用项目中的Android图片缓存技术

    前不久搞的Android图片缓存,刚开始引入开源的框架,用着还行,但是在开发中遇到问题,就比如universal-image-loader-1.9.5.jar这个框架吧,在加载图片的时候自定义imag ...

  5. 学习开源项目Halo(1) - 初步了解与运行Halo

    文章目录 学习开源项目Halo(1) - 初步了解与运行Halo 0.前言 1.Halo简介 2.Halo项目运行 3.Halo项目涉及到的技术栈 学习开源项目Halo(1) - 初步了解与运行Hal ...

  6. angular+ionic学习之项目构建

    前端时间学习了ionic5+angular12,做一次学习记录,对这阶段学习做一个总结. 安装ionic 本地全局安装 npm install -g ionic 或 // 用tabobao镜像装会快些 ...

  7. 安卓 仿学习app项目

    之前写过一个项目,想把自己写的里面的一些技术点记录下来,也相当于给自己做笔记.同时也跟大家一起分享一下,若碰到同样的问题的朋友,也可以相互交流一下,新手上路,请多多指教.在那期间呢,碰到以及出现过许多 ...

  8. 华为章宇:如何学习开源项目及Ceph的浅析

    http://www.csdn.net/article/2014-04-10/2819247-how-to-learn-opensouce-project-&-ceph/1 最近在学习Ceph ...

  9. 英语学习软件项目Postmortem 结果

    英语学习软件项目Postmortem 结果 整理:马骏   设想和目标 1. 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们的软件的首要目的,是帮助用户记忆单 ...

最新文章

  1. linux注销、关机、重启
  2. 雷林鹏分享:XML 命名空间
  3. Window平台 mysql8.0下载安装方式
  4. Linux一键安装web环境全攻略(阿里云服务器)
  5. 通过LDAP验证Active Directory服务
  6. ReactNative 常见红屏黄屏及终端报错
  7. LeetCode动态规划 环形子数组的最大和
  8. 直接学python3_新手应该学python2还是python3?
  9. 漫谈 - 从技术业务骨干走向管理
  10. uniapp使用网易易盾
  11. 金蝶K3案例教程成本报表
  12. 计算机操作填充柄在哪里,Excel中2010版进行添加自动填充柄的操作方法
  13. Harbor构建企业级私有docker镜像的仓库的开源解决方案
  14. python下对bin文件的处理
  15. 移动端网页的基础制作
  16. 对比PAYPAL和国际信用卡支付的流程
  17. 硬件MSB最高位优先、LSB最低位优先的CRC计算原理详细解释和程序,正算反算成功等效,DS18B20和HTU31D传感器CRC
  18. clear:both的理解
  19. 以太坊毕业设计DAPP开发-彩票的设计与实现
  20. 转杨毅:火箭输得有谱了!

热门文章

  1. 哈工大2021春计算机系统大作业 程序人生-Hello’s P2P
  2. 软件工程师如何测试项目,【软件测试工程师(华为项目)软件工程师面试题目|面试经验】-看准网...
  3. 灵图天行者9 pc版_2019十款优化最佳的PC游戏!第一还是冷饭
  4. python面试题整理
  5. 小波从此逝,江海寄余生,不但是文坛巨擘还是不世出的编程奇才,王小波离世25周年
  6. 组件进阶+渡一教育第二节笔记
  7. linux 封禁端口,Linux 常见攻击端口封杀表
  8. rmd文件怎么转换html文件,RMD文件扩展名 - 什么是.rmd以及如何打开? - ReviverSoft...
  9. Shell脚本创建用户
  10. 使用TP5接入支付宝单笔转账接口(AlipayFundTransUniTransferRequest)