当前位置: 首页 > news >正文

jetcache:阿里这款多级缓存框架一定要掌握

0. 引言

之前我们讲解了本地缓存ehcache组件,在实际应用中,并不是单一的使用本地缓存或者redis,更多是组合使用来满足不同的业务场景,于是如何优雅的组合本地缓存和远程缓存就成了我们要研究的问题,而这一点,阿里开源的jetcache组件帮我们实现了

1. jetcache简介

jetcache是阿里开源的基于java开发的缓存框架,支持多种缓存类型:本地缓存、分布式缓存、多级缓存。能够满足不同业务场景的缓存需求。

jetcache具有上手简单、性能高效、拓展性强的特点。支持缓存预热 、缓存key前缀等功能。结合spring-cache使用,可以实现十分优雅的缓存类型切换

官网地址:https://github.com/alibaba/jetcache
官方文档:https://github.com/alibaba/jetcache/tree/master/docs/CN

2. jetcache使用

1、引入依赖,这里我们使用sringboot项目框架,同时使用redis作为远程缓存。于是我们引入jetcache-starter-redis依赖,这里我的springboot版本为2.6.13

如果是非springboot项目可以参考官网说明配置

在这里插入图片描述

<dependency><groupId>com.alicp.jetcache</groupId><artifactId>jetcache-starter-redis</artifactId><version>2.7.0</version>
</dependency><!--        jetcache2.7.x版本需要额外添加该依赖-->
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.3.1</version>
</dependency>

对应的版本说明如下:springboot与jetcache版本关系

在这里插入图片描述

2、修改配置文件,配置redis地址和线程数

jetcache:# 统计间隔,0表示不统计,开启后定期在控制台输出缓存信息statIntervalMinutes: 15# 是否把cacheName作为远程缓存key前缀areaInCacheName: false# 本地缓存配置local:default: # default表示全部生效,也可以指定某个cacheName# 本地缓存类型,其他可选:caffeine/linkedhashmaptype: linkedhashmapkeyConvertor: fastjson# 远程缓存配置remote:default: # default表示全部生效,也可以指定某个cacheNametype: redis# key转换器方式nkeyConvertor: fastjsonbroadcastChannel: projectA# redis序列化方式valueEncoder: javavalueDecoder: java# redis线程池poolConfig:minIdle: 5maxIdle: 20maxTotal: 50# redis地址与端口host: 127.0.0.1port: 6379

更详细的参数配置可参考官网说明:https://github.com/alibaba/jetcache/blob/master/docs/CN/Config.md

在这里插入图片描述

3、启动类添加注解@EnableCreateCacheAnnotation,开启缓存,添加@EnableMethodCache(basePackages = "com.example.jetcachedemo")注解,配置缓存方法扫描路径

4、使用缓存可以通过三种方式:

  • 方式一(推荐)AOP模式:通过@Cached,@CacheUpdate,@CacheInvalidate注解
@RestController
@RequestMapping("user")
public class UserController {@GetMapping("getRemote")@Cached(name="userCache:", key = "#id", expire = 3600, timeUnit = TimeUnit.SECONDS, cacheType = CacheType.REMOTE)public User getRemote(Long id){// 直接新建用户,模拟从数据库获取数据User user = new User();user.setId(id);user.setName("用户remote"+id);user.setAge(23);user.setSex(1);System.out.println("第一次获取数据,未走缓存:"+id);return user;}@GetMapping("getLocal")@Cached(name="userCache:", key = "#id", expire = 3600, timeUnit = TimeUnit.SECONDS, cacheType = CacheType.LOCAL)public User getLocal(Long id){// 直接新建用户,模拟从数据库获取数据User user = new User();user.setId(id);user.setName("用户local"+id);user.setAge(23);user.setSex(1);System.out.println("第一次获取数据,未走缓存:"+id);return user;}@GetMapping("getBoth")@Cached(name="userCache:", key = "#id", expire = 3600, timeUnit = TimeUnit.SECONDS, cacheType = CacheType.BOTH)public User getBoth(Long id){// 直接新建用户,模拟从数据库获取数据User user = new User();user.setId(id);user.setName("用户both"+id);user.setAge(23);user.setSex(1);System.out.println("第一次获取数据,未走缓存:"+id);return user;}@PostMapping("updateUser")@CacheUpdate(name = "userCache:", key = "#user.id", value = "#user")public Boolean updateUser(@RequestBody User user){// TODO 更新数据库return true;}@PostMapping("deleteUser")@CacheInvalidate(name = "userCache:", key = "#id")public Boolean deleteUser(Long id){// TODO 从数据库删除return true;}}

这里要注意实体类User一定要实现序列化,即声明Serializable

@Data
public class User implements Serializable {private Long id;private String name;private Integer age;private Integer sex;
}
  • 方式二 API模式:通过@CreateCache,注:在jetcache 2.7 版本CreateCache注解已废弃,不推荐使用
@RestController
@RequestMapping("user2")
public class User2Controller {@CreateCache(name= "userCache:", expire = 3600, timeUnit = TimeUnit.SECONDS, cacheType = CacheType.BOTH)private Cache<Long, Object> userCache;@GetMapping("get")public User get(Long id){if(userCache.get(id) != null){return (User) userCache.get(id);}User user = new User();user.setId(id);user.setName("用户both"+id);user.setAge(23);user.setSex(1);userCache.put(id, user);System.out.println("第一次获取数据,未走缓存:"+id);return user;}@PostMapping("updateUser")public Boolean updateUser(@RequestBody User user){// TODO 更新数据库userCache.put(user.getId(), user);return true;}@PostMapping("deleteUser")public Boolean deleteUser(Long id){// TODO 从数据库删除userCache.remove(id);return true;}}
  • 方式三 高级API模式:通过CacheManager,2.7 版本才可使用

(1)添加依赖

<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>2.0.25</version>
</dependency>

(2)书写配置类

@Configuration
public class JetcacheConfig {@Autowiredprivate CacheManager cacheManager;private Cache<Long, Object> userCache;@PostConstructpublic void init(){QuickConfig qc = QuickConfig.newBuilder("userCache:").expire(Duration.ofSeconds(3600)).cacheType(CacheType.BOTH)// 本地缓存更新后,将在所有的节点中删除缓存,以保持强一致性.syncLocal(false).build();userCache = cacheManager.getOrCreateCache(qc);}@Beanpublic Cache<Long, Object> getUserCache(){return userCache;}
}

(3)调用代码

@RestController
@RequestMapping("user3")
public class User3Controller {@AutowiredJetcacheConfig jetcacheConfig;@Autowiredprivate Cache<Long, Object> userCache;@GetMapping("get")public User get(Long id){if(userCache.get(id) != null){return (User) userCache.get(id);}User user = new User();user.setId(id);user.setName("用户both"+id);user.setAge(23);user.setSex(1);userCache.put(id, user);System.out.println("第一次获取数据,未走缓存:"+id);return user;}@PostMapping("updateUser")public Boolean updateUser(@RequestBody User user){// TODO 更新数据库userCache.put(user.getId(), user);return true;}@PostMapping("deleteUser")public Boolean deleteUser(Long id){// TODO 从数据库删除userCache.remove(id);return true;}}

多级缓存的形式,会先从本地缓存获取数据,本地获取不到会从远程缓存获取

5、启动redis,启动演示项目

注意,如果启动出现NoClassDefFoundError: redis/clients/util/PoolNoClassDefFoundError: redis/clients/jedis/UnifiedJedis报错,说明springboot与jetcache版本不一致,对应关系可参考上述第一步中的说明
同时如果使用的是jetcache2.7.x版本,因为该版本中有jedis包的依赖,需要额外添加如下依赖,或者将jetcache版本将至2.6.5以下

<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.3.1</version>
</dependency>

3. 测试

3.1 方式一测试

1、访问localhost:8088/user/getRemote?id=1

在这里插入图片描述

因为配置的是远程缓存,在redis中也能看到对应的key

在这里插入图片描述

2、访问localhost:8088/user/getLocal?id=1,这个方法是从本地缓存获取的,现在只有远程缓存上有数据,我们调用发现缓存数据还是拿到了,这说明当我们在配置文件中配置了本地缓存和远程缓存后,方式一中本地缓存和远程缓存会自动相互调用

比如本地缓存有这个key,redis中没有,通过远程缓存方式访问时,会先从redis获取,如果没有会自动获取本地缓存,但是数据还是存储在本地缓存,并不会同步到redis上,这样更加灵活的实现了多级缓存架构

在这里插入图片描述

3.2 方式二测试

1、再测试下CreateCache的形式:localhost:8088/user2/get?id=4

在这里插入图片描述

正常获取了,并且redis中也有了对应的值

在这里插入图片描述
而当我们把缓存方式更改为LOCAL后,再访问localhost:8088/user2/get?id=5

@CreateCache(name= "userCache:", expire = 3600, timeUnit = TimeUnit.SECONDS, cacheType = CacheType.LOCAL)

会发现redis中就没有对应缓存了,只在本地缓存存在,说明我们指定本地缓存的形式成功了

在这里插入图片描述

3.3 方式三测试

1、调用localhost:8088/user3/get?id=11

在这里插入图片描述

redis中缓存设置成功!

在这里插入图片描述

4. 常见报错

1、 ClassNotFoundException: com.alibaba.fastjson.JSON
解决:添加依赖

<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>2.0.25</version>
</dependency>

2、NoClassDefFoundError: redis/clients/jedis/UnifiedJedis
解决:
添加依赖

<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>4.3.1</version>
</dependency>

或者将jetcache版本降低至2.6.5以下

演示源码

https://gitee.com/wuhanxue/wu_study/tree/master/demo/jetcache-demo

相关文章:

jetcache:阿里这款多级缓存框架一定要掌握

0. 引言 之前我们讲解了本地缓存ehcache组件&#xff0c;在实际应用中&#xff0c;并不是单一的使用本地缓存或者redis&#xff0c;更多是组合使用来满足不同的业务场景&#xff0c;于是如何优雅的组合本地缓存和远程缓存就成了我们要研究的问题&#xff0c;而这一点&#xff…...

干货 | 如何做一个简单的访谈研究?

Hello&#xff0c;大家好&#xff01; 这里是壹脑云科研圈&#xff0c;我是喵君姐姐~ 心理学中研究中&#xff0c;大家常用的研究方法大多是实验法、问卷调查法等&#xff0c;这些均是定量研究。 其实&#xff0c;作为质性研究中常用的访谈法&#xff0c;可对个体的内心想法进…...

4年外包出来,5次面试全挂....

我的情况 大概介绍一下个人情况&#xff0c;男&#xff0c;毕业于普通二本院校非计算机专业&#xff0c;18年跨专业入行测试&#xff0c;第一份工作在湖南某软件公司&#xff0c;做了接近4年的外包测试工程师&#xff0c;今年年初&#xff0c;感觉自己不能够再这样下去了&…...

基于遗传算法优化的核极限学习机(KELM)分类算法-附代码

基于遗传算法优化的核极限学习机(KELM)分类算法 文章目录 基于遗传算法优化的核极限学习机(KELM)分类算法1.KELM理论基础2.分类问题3.基于遗传算法优化的KELM4.测试结果5.Matlab代码 摘要&#xff1a;本文利用遗传算法对核极限学习机(KELM)进行优化&#xff0c;并用于分类 1.KE…...

评判需求优先级5大规则和方法(纯干货):

在划分用户需求时&#xff0c;需秉承需求任务紧跟核心业务指标&#xff0c;按照一定的规则和方法进行优先级的划分。 常见评判需求优先级规则有&#xff1a;四象限法则、KANO模型、二八原则、产品生命周期法、ROI评估法。 一、四象限法则 四象限法则是以【重要】和【紧急】程度…...

c++ 11标准模板(STL) std::vector (七)

定义于头文件 <vector> template< class T, class Allocator std::allocator<T> > class vector;(1)namespace pmr { template <class T> using vector std::vector<T, std::pmr::polymorphic_allocator<T>>; }(2)(C17…...

Contest3137 - 2022-2023-2 ACM集训队每月程序设计竞赛(1)五月月赛

A 1! 5! 46 169 有一种数字&#xff0c;我们称它为 纯真数。 它等于自身每一个数位的阶乘之和。请你求出不超过n的所有 纯真数。(注&#xff1a;纯真数不含有前导0&#xff09;数据范围1e18 纯真数只有四个&#xff0c;注意0!1 1,2,145,40585 int n;cin>>n;int res[]{…...

如何使用 YOLOv8 神经网络检测图像中的物体

对象检测是一项计算机视觉任务,涉及识别和定位图像或视频中的对象。它是许多应用的重要组成部分,例如自动驾驶汽车、机器人和视频监控。 多年来,已经开发了许多方法和算法来查找图像中的对象及其位置。执行这些任务的最佳质量来自使用卷积神经网络。 YOLO 是这项任务最流行的…...

Python每日一练:小艺读书醉酒的狱卒非降序数组(详解快排)

文章目录 前言一、小艺读书二、醉酒的狱卒三、非降序数组总结 前言 今天这个非降序数组&#xff0c;阅读解理小学水平&#xff0c;说起来都是泪啊。我折腾了一天都没搞定&#xff0c;从冒泡写到快速排序。换了几种都还不行&#xff0c;我又给快排加上插入排序。结果还是不能全…...

手麻系统源码,PHP手术麻醉临床信息系统源码,手术前管理模块功能

手麻系统源码&#xff0c;PHP手术麻醉临床信息系统源码&#xff0c;手术前管理模块功能 术前管理模块主要有手术排班、手术申请单、手术通知单、手术知情同意书、输血血液同意书、术前查房记录、术前访视、风险评估、手术计划等功能。 功能&#xff1a; 手术排班&#xff1a;…...

AUTOSAR - ComM - 学习一 :基础知识+配置

目录 1、概述 1.1、总览 1.2、功能描述 1.3、依赖关系 2、功能SPEC 2.1、PNC...

手把手教你搭建ROS阿克曼转向小车之(增量式PID代码实现)

在上一篇文章中我们已经成功的把编码器的反馈值给计算出来&#xff0c;这篇文章将会讲解怎么使用反馈回来的速度值进行PID计算&#xff0c;从而闭环控制电机的速度。 PID算法介绍 1.开环控制系统 开环控制系统(open-loop control system)是指被控对象的输出(被控制量)对控制器…...

C语言函数大全-- t 开头的函数

C语言函数大全 本篇介绍C语言函数大全-- t 开头的函数 1. tan&#xff0c;tanf&#xff0c;tanl 1.1 函数说明 函数声明函数功能double tan(double x)计算 以弧度 x 为单位的角度的正切值&#xff08;double&#xff09;float tanf(float x)计算 以弧度 x 为单位的角度的正…...

安卓系统APP稳定性测试分析的研究报告

目录 第一章&#xff1a;概念 第二章&#xff1a;重要性 第三章&#xff1a;意义和作用 第四章&#xff1a;行业现状 第五章&#xff1a;常见测试方法和工具 第六章&#xff1a;实际测试场景 第七章&#xff1a;测试方案 第八章&#xff1a;测试方法 第九章&#xff1…...

【Java基础】集合

一、集合概述 为了方便对多个对象进行存储和操作&#xff0c;集合是一种Java容器&#xff0c;可以动态地把多个对象引用放入容器中 数组存储的特点 一旦初始化后&#xff0c;长度不可改变&#xff0c;元素类型不可改变提供的方法很少&#xff0c;对于添加、删除、获取实际元…...

【Android入门到项目实战-- 9.1】—— 传感器的使用教程

目录 传感器的定义 三大类型传感器 1、运动传感器 2、环境传感器 3、位置传感器 传感器开发框架 1、SensorManager 2、Sensor 3、SensorEvent 4、SensorEventListener 一、使用传感器开发步骤 1、获取传感器信息 1)、获取传感器管理器 2)、获取设备的传感器对象列…...

yolov8 浅记

目录 Pre: 1. YOLOv8 概述 2. 模型结构设计 3. Loss 计算 4.训练数据增强 5. 训练策略 6、部署推理 End Pre: yolo系列发布时间&#xff1a; 先贴一下yolo各系列的发布时间&#xff08;说出来很丢人&#xff0c;我以为 yolox是 最新的&#xff09;&#xff1a; yoloX 2…...

前端009_类别模块_修改功能

第九章 1、需求分析2、Mock添加查询数据3、Mock修改数据4、Api调用回显数据5、提交修改后的数据6、效果1、需求分析 需求分析 当点击 编辑 按钮后,弹出编辑窗口,并查询出分类相关信息进行渲染。修改后点击 确定 提交修改后的数据。 2、Mock添加查询数据 请求URL: /article/…...

2022级吉林大学面向对象第一次上机测试

【注&#xff1a;解答全部为本人所写&#xff0c;仅供同学们学习时参考使用&#xff0c;请勿照搬抄袭&#xff01;】 1、 1&#xff09;略 2&#xff09;如果main,f1,g1,g2或更多的函数之间有更为复杂的调用关系&#xff0c;头文件一般按怎样的规律写呢&#xff1f; 一般情况下…...

计算机体系结构总结:内存一致性模型 Memory consistency Model

存储一致性是为了保证多线程背景下的访存顺序&#xff0c;多线程的语句是可以交错执行&#xff0c;使得顺序不同产生不同的执行结果。 下面P2的输出结果可能是什么&#xff1f; P1, P2两个线程的语句是可以交叉执行的&#xff0c;比如1a, 2a, 2b, 1b&#xff1b;一个线程内的语…...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

接口自动化测试:HttpRunner基础

相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具&#xff0c;支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议&#xff0c;涵盖接口测试、性能测试、数字体验监测等测试类型…...

Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换

目录 关键点 技术实现1 技术实现2 摘要&#xff1a; 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式&#xff08;自动驾驶、人工驾驶、远程驾驶、主动安全&#xff09;&#xff0c;并通过实时消息推送更新车…...

【网络安全】开源系统getshell漏洞挖掘

审计过程&#xff1a; 在入口文件admin/index.php中&#xff1a; 用户可以通过m,c,a等参数控制加载的文件和方法&#xff0c;在app/system/entrance.php中存在重点代码&#xff1a; 当M_TYPE system并且M_MODULE include时&#xff0c;会设置常量PATH_OWN_FILE为PATH_APP.M_T…...