【开发篇】十二、缓存框架JetCache

文章目录

  • 0、介绍
  • 1、JetCache远程缓存
  • 2、JetCache本地缓存
  • 3、标准配置文件
  • 4、JetCache方法缓存注解--@Cached
  • 5、@Cached
  • 4、@CacheUpdate
  • 5、@CacheInvalidate
  • 6、@CacheRefresh
  • 7、缓存统计报告

上篇完成了Spring Cache底层技术的各种切换,但各个技术有各自的优缺点,因此阿里的Jetcache框架出现。 注意Jetcache是一个框架,做的是一个整合和封装,自身不是像redis一样的缓存实现技术,Jetcache框架底层还得依靠具体的缓存实现技术,它是和Spring Cache同等级的,用来替换Spring Cache的。

0、介绍

JetCache对SpringCache进行了封装,在原有功能基础上实现了多级缓存、缓存统计、自动刷新、异步调用、数据报表等功能

JetCache设定了本地缓存与远程缓存的多级缓存解决方案,其中本地缓存(local)支持:

  • LinkedHashMap
  • Caffeine

远程缓存(remote)支持:

  • Redis
  • Tair

1、JetCache远程缓存

先引入依赖

<dependency>    <groupId>com.alicp.jetcache</groupId>   <artifactId>jetcache-starter-redis</artifactId>    <version>2.6.2</version>
</dependency>

远程缓存的属性配置:

jetcache:  remote:    default:      type: redis      host: localhost      port: 6379   password: admin1234   poolConfig:        maxTotal: 50# 再定义一个缓存区域也行myArea:type: redishost: .......

@EnableCreateCacheAnnotation启动用注解来创建缓存,开启后就可以用@CreateCache来创建一个缓存对象。

@SpringBootApplication@EnableCreateCacheAnnotationpublic class CacheApplication {    public static void main(String[] args) {   SpringApplication.run(CacheApplication.class, args);    }}

使用@CreateCache注解声明一个缓存对象:

@Service
public class SMSCodeServiceImpl implements SMSCodeService {@CreateCache(area = "default", name = "smsCache::", expire = 3600, timeUnit = TimeUnit.SECONDS, cacheType = CacheType.REMOTE)  private Cache<String, String> jetSMSCache;//...}

注意@CreateCache注解的属性:

  • area:用哪块存储空间,默认值为default,即配置文件里的jetcache.remote.default及其下面的配置,可以再自己定义区域
  • name:key的分组前缀,常用str::或者str_
  • expire:过期时间,单位默认秒
  • timeUnit:时间单位,默认值秒
  • cacheType:缓存类型,local即本地缓存,remote即远程缓存,all即两个都写,默认远程缓存

操作缓存:使用缓存对象.put和get

@Service
public class SMSCodeServiceImpl implements SMSCodeService {    @Override   public String sendCodeToSMS(String tele) {     String code = this.codeUtils.generator(tele);  jetSMSCache.put(tele,code);    //putreturn code;    }   @Override    public boolean checkCode(String tele,String code) {  String value = jetSMSCache.get(tele);     //getreturn code.equals(value);}
}

重启服务,调用之前的缓存接口查看效果。出现了一个莫名奇妙的循环依赖,先临时解决下,跳过了:

spring:main:allow-circular-references: true

发现接口调用正常,启动日志也输出了相关信息:

在这里插入图片描述

2、JetCache本地缓存

和远程一样,引入依赖后,配置文件不同:

jetcache:  local:    default:     type: linkedhashmap      keyConvertor: fastjson # 即key不是String时,用哪个转换器转为String

再后面一样的操作,开启缓存注解支持、声明缓存对象、put和get都一样,需要注意的是上面的CacheType属性改为Local

@CreateCache(name = "smsCache::", expire = 3600, cacheType = CacheType.LOCAL)  
private Cache<String, String> jetSMSCache;

3、标准配置文件

JetCache能同时支持本地和远程缓存,所以标准的配置文件写一起就行:

jetcache:  statIntervalMinutes: 15  areaInCacheName: false    # 即key里加不加area的名字,true时key形如default_myname::keylocal:    default:      type: linkedhashmap      keyConvertor: fastjson      limit: 100  remote:default:      host: localhost      port: 6379      type: redis      keyConvertor: fastjson      valueEncoder: java      valueDecoder: java      poolConfig:        minIdle: 5        maxIdle: 20       maxTotal: 50

关于配置的含义:

在这里插入图片描述

4、JetCache方法缓存注解–@Cached

上面写缓存得创建JetCache缓存对象后put和get,如何像@Cacheable注解一样,对整个方法的结果通过加注解来自动写查缓存?

请添加图片描述

答案是在@EnableCreateCacheAnnotation的基础上,再加注解@EnableMethodCache(basePackages = "com.mydemo"),开启对方法缓存注解的支持,basePackeages属性写需要用到方法缓存注解的包路径。

@SpringBootApplication
@EnableCreateCacheAnnotation  ####!
@EnableMethodCache(basePackages = "com.mydemo") ####!
public class JetCacheApplication {  public static void main(String[] args) { SpringApplication.run(JetCacheApplication.class, args);    }
}

@Cached注解加需要缓存的方法上,如此查到的Book对象就被缓存到default的Area,且是远程缓存

@Service
public class BookServiceImpl implements BookService {    @Autowired    private BookDao bookDao;   @Cached(name = "smsCache_", key = "#id", expire = 3600) @Override      public Book getById(Integer id) {return bookDao.selectById(id);    }}

上面@Cache注解的cacheType属性没写,那就是默认的远程缓存。此时,调用接口返回正常,但接口日志有异常:

在这里插入图片描述

需要加一个配置,指定key的转换器给本地和远程缓存:

在这里插入图片描述

再重启,接口正常,但日志仍有报错NotSerializableException,这个就很明确了,Java对象存进缓存时,要转为json,而要存的对象的实体类没去实现序列化接口,实现下Serializable接口就行。

在这里插入图片描述
实现序列化接口后,别忘了要在配置中加:

valueEncoder: java      
valueDecoder: java    

即,编码时的是java对象,解码时,也要转汇Java对象。

5、@Cached

重新整理下@Cached注解,它的属性和@CreateCache的一样,但多了几个,放一起整理了:

属性默认值描述
areadefault如果在配置中配置了多个缓存area,在这里指定使用哪个area
name未定义($$undefined$$)指定缓存的唯一名称,不是必须的,如果没有指定,会使用类名+方法名。name会被用于远程缓存的key前缀。另外在统计中,一个简短有意义的名字会提高可读性。
key未定义使用SpEL来指定缓存的key值,如#id 、#p0
expire-2147483648过期时间
timeUnitTimeUnit.SECONDS过期时间的单位
cacheTypeCacheType.REMOTE缓存的类型,可选CacheType.REMOTE、CacheType.LOCAL、CacheType.BOTH。如果定义为BOTH,会使用LOCAL和REMOTE组合成两级缓存
localLimit-2147483648如果cacheType为LOCAL或BOTH,这个参数指定本地缓存的最大元素数量,以控制内存占用。如果注解上没有定义,会使用全局配置,如果此时全局配置也没有定义,则为100
localExpire-2147483648仅当cacheType为BOTH时适用,为内存中的Cache指定一个不一样的超时时间,通常应该小于expire
serialPolicy未定义指定远程缓存的序列化方式。可选值为SerialPolicy.JAVA和SerialPolicy.KRYO。如果注解上没有定义,会使用全局配置,如果此时全局配置也没有定义,则为SerialPolicy.JAVA
keyConvertor未定义指定KEY的转换方式,用于将复杂的KEY类型转换为缓存实现可以接受的类型,当前支持KeyConvertor.FASTJSON和KeyConvertor.NONE。NONE表示不转换,FASTJSON可以将复杂对象KEY转换成String。如果注解上没有定义,会使用全局配置
enabledtrue是否激活缓存。例如某个dao方法上加缓存注解,由于某些调用场景下不能有缓存,所以可以设置enabled为false,正常调用不会使用缓存,在需要的地方可使用CacheContext.enableCache在回调中激活缓存,缓存激活的标记在ThreadLocal上,该标记被设置后,所有enable=false的缓存都被激活
cacheNullValuefalse当方法返回值为null的时候是否要缓存
condition未定义使用SpEL指定条件,如果表达式返回true的时候才去缓存中查询
postCondition未定义使用SpEL指定条件,如果表达式返回true的时候才更新缓存,该评估在方法执行后进行,因此可以访问到#result

整体有点像@Cacheable注解。重点注意下area,一块一块的缓存区域。

4、@CacheUpdate

方法上加了@Cached后,方法返回值被写进缓存,但如果持久层被update,再查数据时。从缓存中拿到的数据就不对了,可通过在更新持久层的方法上加@CacheUpdate注解解决。先看这个注解属性:

属性默认值描述
areadefault缓存区域,注意和上面@Cached时所在的区域保持一致
namekey前缀,注意和上面@Cached时的name一致
key未定义SpEL表达式,根据当前方法的形参拼出@Cached时的key,如@Cached的方法形参为id,key为#id。而@CacheUpdate所在方法形参为Book对象book,则key为#book.id
value要更新的值
condition未定义使用SpEL指定条件,如果表达式返回true才执行更新,可访问方法结果#result
@Service
public class BookServiceImpl implements BookService {@CacheUpdate(name = "smsCache_", key = "#book.id", value = "#book")    public boolean update(Book book) {            return bookDao.updateById(book) > 0;       }}

对照上面的@Cached注解的key来看这个@CacheUpdate的key。此时,调用查询接口,返回更新后的数据,且不会查持久层,因为缓存已被更新,到不了持久层。

5、@CacheInvalidate

和更新一样,如果持久层数据被删除,如何通知到缓存呢,答案是@CacheInvalidate注解。

@Service
public class BookServiceImpl implements BookService {@CacheInvalidate(name = "smsCache_", key = "#id")    public boolean delete(Integer id) {        return bookDao.deleteById(id) > 0;    }
}

这样,当delete方法执行,持久层数据被删除时,缓存也就被删掉了。此时,调用查询接口,会去查持久层!!查持久层才合理,缓存里都没数据了,不去持久层看看停在缓存层干嘛 。这个注解属性和更新缓存注解一样,少了value,参照上文。

6、@CacheRefresh

以上,不管是更新还是删除,总在我的服务中,我自己掌握,我自己加了注解去通知缓存跟着变。但如果持久层更新的操作是在别的部门管理的服务里呢?即在缓存层无感知,如何保证数据最新,答案是@CacheRefresh,每隔一定间隔去查数据库,刷新缓存值。 先看注解属性:

属性默认值描述
refresh刷新间隔,谨慎设置,过小会导致查持久层频率太高,给数据库带来压力
timeUnitTimeUnit.SECONDS时间单位
stopRefreshAfterLastAccess-2147483648指定该key多长时间没有访问就停止刷新,如果不指定会一直刷新
refreshLockTimeout-2147483648类型为BOTH/REMOTE的缓存刷新时,同时只会有一台服务器在刷新,这台服务器会在远程缓存放置一个分布式锁,此配置指定该锁的超时时间

在这里插入图片描述
以上即,查到的Book对象缓存起来,且没10秒去数据库查一下,然后刷新缓存里的Book值

7、缓存统计报告

在服务配置文件application.yaml中加以下配置:

jetcache:statIntervalMinutes: 15# statInterval即统计间隔,也就是15分钟一统计

重启服务,控制台每隔15分钟输出一次统计数据,值为0时即不统计,(直接不写就行,不用写了又给个0值),效果如下:
在这里插入图片描述

查询26次,命中缓存21次。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/144525.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

UE5 ChaosVehicles载具研究

一、基本组成 载具Actor类名称&#xff1a;WheeledVehiclePawn Actor最原始的结构 官方增加了两个摇臂相机&#xff0c;可以像驾驶游戏那样切换多机位、旋转观察 选择骨骼网格体、动画蓝图类、开启物理模拟 二、SportsCar_Pawn 角阻尼&#xff1a;物体旋转的阻力。数值越大…

3D孪生场景搭建:模型阵列摆放

阵列摆放概念 阵列摆放是指将物体、设备或元件按照一定的规则和间距排列组合的方式。在工程和科学领域中&#xff0c;阵列式摆放常常用于优化空间利用、提高效率或增强性能。 阵列摆放通常需要考虑间距、角度、方向、对称性等因素&#xff0c;以满足特定的要求和设计目标。不同…

同城信息服务源码 本地生活服务小程序源码

同城信息服务源码 本地生活服务小程序源码 功能介绍&#xff1a; 基本设置&#xff1a;网站参数、安全设置、分站管理、支付设置、操作日志、地区设置、公交地铁、国际区号、清理缓存、模板风格、模块管理、域名管理、底部菜单、消息通知、登录设置 其他设置&#xff1a;关键…

Python 基于 Yolov8 + CPU 实现物体检测

目录 一、开发环境 二、安装 Python 基于 Yolov8 物体检测关联库 2.1 打开命令提示符&#xff08;cmd&#xff09;或终端&#xff0c;安装库 2.2 关联库安装过程遇到的问题 三、基于 Yolov8 物体检测代码实现&#xff08;完整&#xff09; 3.1 Yolov8 物体检测完整代码…

力扣:112. 路径总和(Python3)

题目&#xff1a; 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节点值相加等于目标和 targetSum 。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 叶子节点…

Flink状态

8.1 Flink中的状态 8.1.1 概述 状态的分类 1&#xff09;托管状态&#xff08;Managed State&#xff09;和原始状态&#xff08;Raw State&#xff09; Flink的状态有两种&#xff1a;托管状态&#xff08;Managed State&#xff09;和原始状态&#xff08;Raw State&#…

PICO首届XR开发者挑战赛正式启动,助推行业迈入“VR+MR”新阶段

9月25日&#xff0c;“PICO 2023首届XR开发者挑战赛”&#xff08;下文简称“挑战赛”&#xff09;媒体启动会在北京圆满落幕&#xff0c;官方赛事报名通道已于今日开启。据悉&#xff0c;本次挑战赛是PICO首次针对全球开发者举办的大型挑战赛事&#xff0c;旨在与开发者保持连…

redis介绍

一、简介 Redis 与其他 key - value 缓存产品有以下三个特点&#xff1a; Redis支持数据的持久化&#xff0c;可以将内存中的数据保存在磁盘中&#xff0c;重启的时候可以再次加载进行使用。 Redis不仅仅支持简单的key-value类型的数据&#xff0c;同时还提供list&#xff0c;…

从入门到精通:详解SVN版本控制系统的使用方法

从入门到精通&#xff1a;详解SVN版本控制系统的使用方法 一、引言1.1、版本控制的概念和重要性1.2、流行的版本控制系统SVN 二、SVN基础知识2.1、SVN的基本概念和术语解释2.2、SVN的工作原理和架构 三、创建SVN仓库3.1、创建本地仓库3.2、配置访问权限 四、使用SVN进行版本控制…

基于视频技术与AI检测算法的体育场馆远程视频智能化监控方案

一、方案背景 近年来&#xff0c;随着居民体育运动意识的增强&#xff0c;体育场馆成为居民体育锻炼的重要场所。但使用场馆内的器材时&#xff0c;可能发生受伤意外&#xff0c;甚至牵扯责任赔偿纠纷问题。同时&#xff0c;物品丢失、人力巡逻成本问题突出&#xff0c;体育场…

企业如何寻找适合的CRM系统软件

在数字化转型步伐不断加快的今天&#xff0c;CRM软件成为企业必不可少的一项工具。如果您并不清楚如何寻找合适的CRM系统软件&#xff1f;不妨通过下列几点来寻觅。 1.根据CRM系统行业和类别 例如企业重视营销功能&#xff0c;搜寻营销型CRM软件&#xff1b; 企业希望梳理好…

Open3D 进阶(11)使用GMM-Tree算法对点云配准

GMM-Tree算法 一、算法原理1、主要函数2、参考文献二、代码实现三、结果展示1、点云初始位置2、配准后的位置四、测试数据本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、算法原理 1、

DevExpress WinForms图表组件 - 直观的数据信息呈现方式!(二)

在上文中&#xff08;点击这里回顾>>&#xff09;&#xff0c;我们为大家介绍了DevExpress WinForms图表控件的互动图表、图标设计器及可定制功能等&#xff0c;本文将继续介绍DevExpress WinForms图表控件的数据分析、大数据功能等&#xff0c;欢迎持续关注我们哦~ Dev…

PDF文件超出上传大小?三分钟学会PDF压缩

PDF作为一种流行的文档格式&#xff0c;被广泛用于各种场合&#xff0c;然而有时候PDF文件的大小超出了上传限制&#xff0c;这时候我们就需要采取一些措施来减小PDF文件的大小&#xff0c;下面就给大家分享几个方法&#xff0c;一起来学习下吧~ 方法一&#xff1a;嗨格式压缩大…

基于数据驱动的成本洞察,趣丸科技的FinOps进阶之路~

今年以来&#xff0c;我们注意到越来越多的单位开始积极实践FinOps&#xff0c;而随着FinOps的发展&#xff0c;大家对于其落地过程的关注也更加具体和深入&#xff0c;涉及了账单波动、FinOps的边际效应、成本模型、依赖工具等多个关键问题。 本月「UGeek大咖说」线上直播活动…

【网络协议】Http-中

搜索引擎&#xff1a;搜索引擎是指根据一定的策略、运用特定的计算机程序从互联网上采集信息&#xff0c;在对信息进行组织和处理后&#xff0c;为用户提供检索服务&#xff0c;将检索的相关信息展示给用户的系统。搜索引擎是工作于互联网上的一门检索技术&#xff0c;它旨在提…

表格内日期比较计算

需求&#xff1a;在表格中新增数据&#xff0c;计算开始日期中最早的和结束日期中最晚的&#xff0c;回显到下方。 <el-formref"formRef":model"ruleForm":rules"rules"style"margin-top: 20px;"label-position"top">…

SpringMVC+统一表现层返回值+异常处理器

一、统一表现层返回值 根据我们不同的处理方法&#xff0c;返回的数据格式都会不同&#xff0c;例如添加只返回true|false&#xff0c;删除同理&#xff0c;而查询却返回数据。 Result类 为此我们封装一个result类来用于表现层的返回。 public class Result {//描述统一格式…

vscode调试webpack项目的方法

vscode调试webpack项目的方法 首先安装vscode插件Javascript Debugger 这个插件的介绍也写清楚了&#xff1a; An extension for debugging Node.js programs and Chrome. 那就是用来调试Node.js和Chrome的vscode扩展插件&#xff0c;包括typescript. 然后按F5启动调试&…

力扣每日一题(+日常水几道题)

每日一题1333. 餐厅过滤器 - 力扣&#xff08;LeetCode&#xff09; 简单的按规则排序,去除几个不满足的条件然后排序返回即可 #include<algorithm> class Solution { public:vector<int> filterRestaurants(vector<vector<int>>& restaurants, …