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

Spring Cache的基本使用与分析

概述

使用 Spring Cache 可以极大的简化我们对数据的缓存,并且它封装了多种缓存,本文基于 redis 来说明。

基本使用

1、所需依赖

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

2、配置文件

spring:# redis连接信息redis:host: 192.168.56.10port: 6379cache:# 指定使用的缓存类型type: redis# 过期时间redis:time-to-live: 3600000# 是否开启前缀,默认为trueuse-key-prefix: true# 键的前缀,如果不配置,默认就是缓存名cacheNameskey-prefix: CACHE_# 是否缓存空置,防止缓存穿透,默认为truecache-null-values: true

3、Spring Cache 提供的注解如下,使用方法参见:官方文档,通过这些注解,我们可以方便的操作缓存数据。

  • @Cacheable:触发缓存写入的操作
  • @CacheEvict:触发缓存删除的操作
  • @CachePut:更新缓存,而不会影响方法的执行
  • @Caching:重新组合要应用于一个方法的多个缓存操作,即对一个方法添加多个缓存操作
  • @CacheConfig:在类级别共享一些与缓存有关的常见设置

例如,如果需要对返回结果进行缓存,直接在方法上标注 @Cacheable 注解(在主配置类上需要标注上 @EnableCaching

@Cacheable(cacheNames = "userList") //指定缓存的名字,便于区分不同缓存
public List<User> getUserList() {...
} 

4、redis 默认使用 jdk 序列化,需要我们配置序列化机制,自定义一个配置类,否则存入的数据显示乱码

@EnableCaching //开启缓存
@Configuration
public class MyCacheConfig {@Beanpublic RedisCacheConfiguration redisCacheConfiguration(){RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();//指定键和值的序列化机制config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));return config;}
}

5、使用以上配置后,虽然乱码的问题解决了,但配置文件又不生效了,比如过期时间等,这是因为在初始化时会判断用户是否自定义了配置文件,如果自定义了,原来的就不会生效,源码如下:

private org.springframework.data.redis.cache.RedisCacheConfigurationdetermineConfiguration(ClassLoader classLoader) {//如果配置了,就返回自定义的配置if (this.redisCacheConfiguration != null) {return this.redisCacheConfiguration;}//没配置使用默认的配置Redis redisProperties = this.cacheProperties.getRedis();org.springframework.data.redis.cache.RedisCacheConfiguration config = org.springframework.data.redis.cache.RedisCacheConfiguration.defaultCacheConfig();config = config.serializeValuesWith(SerializationPair.fromSerializer(new JdkSerializationRedisSerializer(classLoader)));if (redisProperties.getTimeToLive() != null) {config = config.entryTtl(redisProperties.getTimeToLive());}if (redisProperties.getKeyPrefix() != null) {config = config.prefixKeysWith(redisProperties.getKeyPrefix());}if (!redisProperties.isCacheNullValues()) {config = config.disableCachingNullValues();}if (!redisProperties.isUseKeyPrefix()) {config = config.disableKeyPrefix();}return config;
}

6、所以,我们也需要手动获取 ttl、prefix 等属性,直接仿照源码就行,将配置类修改为如下:

@EnableCaching //开启缓存
@Configuration
@EnableConfigurationProperties(CacheProperties.class) //缓存的所有配置属性都在这个类里
public class MyCacheConfig {@Beanpublic RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties) {//获取默认配置RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();//指定键和值的序列化机制config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));//获取配置文件的配置CacheProperties.Redis redisProperties = cacheProperties.getRedis();if (redisProperties.getTimeToLive() != null) {config = config.entryTtl(redisProperties.getTimeToLive());}if (redisProperties.getKeyPrefix() != null) {config = config.prefixKeysWith(redisProperties.getKeyPrefix());}if (!redisProperties.isCacheNullValues()) {config = config.disableCachingNullValues();}if (!redisProperties.isUseKeyPrefix()) {config = config.disableKeyPrefix();}return config;}
}

原理分析

在 Spring 中 CacheManager 负责创建管理 Cache,Cache 负责缓存的读写,因此使用 redis 作为缓存对应的就有 RedisCacheManager 和 RedisCache。

打开 RedisCache 源码,我们需要注意这两个方法:

1、读取数据,未加锁

@Override
protected Object lookup(Object key) {byte[] value = cacheWriter.get(name, createAndConvertCacheKey(key));if (value == null) {return null;}return deserializeCacheValue(value);
}

2、读取数据,加锁,这是 RedisCache 中唯一一个同步方法

@Override
public synchronized <T> T get(Object key, Callable<T> valueLoader) {ValueWrapper result = get(key);if (result != null) {return (T) result.get();}T value = valueFromLoader(key, valueLoader);put(key, value);return value;
}

通过打断点的方式可以知道 RedisCache 默认调用的是 lookup(),因此不能应对缓存击穿,如果有相关需求,可以这样配置:@Cacheable(sync = true),开启同步模式,此配置只在 @Cacheable 中才有。

总结

Spring Cache 对于读模式下缓存失效的解决方案:

  • 缓存穿透:cache-null-values: true,允许写入空值
  • 缓存击穿:@Cacheable(sync = true),加锁
  • 缓存雪崩:time-to-live:xxx,设置不同的过期时间

而对于写模式,Spring Cache 并没有相应处理,我们需要使用其它方式处理。


总的来说:

1、对于常规数据(读多写少,及时性、一致性要求不高的数据)完全可以使用 Spring Cache

2、对于特殊数据(比如要求高一致性)则需要特殊处理

相关文章:

Spring Cache的基本使用与分析

概述 使用 Spring Cache 可以极大的简化我们对数据的缓存&#xff0c;并且它封装了多种缓存&#xff0c;本文基于 redis 来说明。 基本使用 1、所需依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-…...

【安全知识】——端口复用隐藏后门

作者名&#xff1a;白昼安全主页面链接&#xff1a; 主页传送门创作初心&#xff1a; 以后赚大钱座右铭&#xff1a; 不要让时代的悲哀成为你的悲哀专研方向&#xff1a; web安全&#xff0c;后渗透技术每日鸡汤&#xff1a; 精彩的人生是在有限的生命中实现无限价值端口复用是…...

Tina_Linux量产测试使用指南_new

OpenRemoved_Tina_Linux_量产测试_使用指南_new 1 概述 文档主要描述如何配置tinatest 并搭建量产测试环境。 1.1 编写目的 • 介绍量产配置方法&#xff1b; • 介绍量产测试环境搭建流程&#xff1b; • 介绍如何使用dragonMAT 软件&#xff1b; • 方便开发人员按照说明…...

STC32单片机 普通 I/O 口中断功能介绍和使用

STC32单片机 普通 I/O 口中断功能和使用✨STC32单片机普通 I/O 口中断&#xff0c;不是传统外部中断. &#x1f516;手册上描述&#xff1a;STC32G 系列支持所有的 I/O 中断&#xff0c;且支持 4 种中断模式&#xff1a;下降沿中断、上升沿中断、低电平中断、高电平中断。每组 …...

计算机学生如何找到第一份实习?

作为一名计算机专业的学生&#xff0c;找到第一份实习是非常重要的一步&#xff0c;它不仅可以帮助你更好地了解行业&#xff0c;增加实践经验&#xff0c;还可以为即将到来的校招提供有力支持。计算机专业的校招&#xff0c;每年都在变得越来越卷。5年前&#xff0c;可能你只要…...

《Python机器学习》基础代码

1&#xff0c;要学习Python机器学习,第一步就是读入数据,这里我们以读入excel的数据为例,利用jupyter notebook来编码,具体教程看这个视频 推荐先上传到jupyter notebook,再用名字.xlsx来导入 Jupyter notebook导入Excel数据的两种方法介绍_哔哩哔哩_bilibili 2&#xff0c;…...

【前端】JS异步加载

文章目录为什么要异步加载如何实现异步加载参考为什么要异步加载 两个原因其实是一个意思。 原因1&#xff1a; JS是单线程的语言&#xff0c;它会同步的执行代码&#xff0c;从上往下执行 但是&#xff0c;一旦网络不好&#xff0c;或要加载的js文件过大的话&#xff0c;会…...

【MySQL】SQL语言的五个部分

DQL 数据查询语言&#xff08;Data Query Language&#xff0c;DQL&#xff09;&#xff1a;DQL主要用于数据的查询&#xff0c;其基本结构是使用SELECT子句&#xff0c;FROM子句和WHERE子句的组合来查询一条或多条数据。 DML 数据操作语言&#xff08;Data Manipulation La…...

详细的IO面试题汇总

IO 流简介 IO 即 Input/Output&#xff0c;输入和输出。数据输入到计算机内存的过程即输入&#xff0c;反之输出到外部存储&#xff08;比如数据库&#xff0c;文件&#xff0c;远程主机&#xff09;的过程即输出。数据传输过程类似于水流&#xff0c;因此称为 IO 流。IO 流在…...

在Linux终端管理你的密码!

大家好&#xff0c;我是良许。 现在是互联网时代&#xff0c;我们每天都要跟各种 APP 、网站打交道&#xff0c;而这些东西基本上都需要注册才可以使用。 但是账号一多&#xff0c;我们自己都经常记不清对应的密码了。有些小伙伴就一把梭&#xff0c;所有的账号密码都是一样。…...

【设计模式】策略模式在Java工程中应用

在之前的文章中&#xff0c;曾经给大家介绍过策略模式&#xff1a;【设计模式】策略模式&#xff0c;在该篇文章中&#xff0c;我们曾很清楚的说到&#xff0c;策略模式主要解决的问题是&#xff1a;在有多种算法相似的情况下&#xff0c;解决使用 if...else 所带来的复杂和难以…...

Linux驱动开发工程师需要掌握哪些技能?

一、前言 Linux驱动开发是一项高度技术性的工作&#xff0c;需要深厚的编程技能和对计算机硬件的深入理解。随着物联网、人工智能等领域的快速发展&#xff0c;Linux驱动开发工程师的需求日益增加。在这篇文章中&#xff0c;我将为您介绍一条Linux驱动开发工程师的学习路线&am…...

【人脸识别】FROM:提升遮挡状态下的人脸识别效果

论文题目&#xff1a;《End2End Occluded Face Recognition by Masking Corrupted Features》 论文地址&#xff1a;https://arxiv.org/pdf/2108.09468v3.pdf 代码地址&#xff1a;https://github.com/haibo-qiu/from 1.前言 人脸识别技术已经取得了显著的进展&#xff0c;主要…...

浏览器缓存

什么是缓存? 当第一次访问网站的时候,比如www.baidu.com,电脑会图片,文件等下载下来,当第二次访问网站的时候,网站就会直接被加载出来. 缓存的好处? 减轻服务器压力,减少请求的放松.提高性能,在本地打开资源肯定比在服务器上获取要快减少宽带的消耗,当我们使用缓存时,只会…...

【软考 系统架构设计师】论文范文③ 论数据访问层设计技术及其应用

>>回到总目录<< 文章目录 论数据访问层设计技术及其应用范文摘要正文论数据访问层设计技术及其应用 在信息系统的开发与建设中,分层设计是一种常见的架构设计方法,区分层次的目的是为了实现“高内聚低耦合”的思想。分层设计能有效简化系统复杂性,使设计结构清…...

802.11 MCS 的最低SNR分析

常常看到这样的表格: 那么这个SNR如何而来? 看看RSSI和SNR的关系,它们之间隔了一个noise floor。从表格看得出,这个底噪在-80~-90之间。 而SNR的核心,也有类似的原因,它和BER有关。...

用于C++的对象关系映射库—YB.ORM

1 介绍YB.ORM YB.ORM 旨在简化与关系数据库交互的 C 应用程序的开发。 对象关系映射器(ORM) 通过将数据库表映射到类并将表行映射到应用程序中的对象来工作&#xff0c;这种方法可能不是对每个数据库应用程序都是最佳的&#xff0c;但它被证明在需要复杂逻辑和事务处理的应用程…...

Cesium 100K数据加载 支持弹窗 动态更改位置

前言&#xff1a;今天总结关于point、label、billboard海量数据加载。后续会研究下大量model加载以及大bim(几百G上T)模型记载 海量点加载 弹窗 加载点位时&#xff0c;不加载弹窗。点击点位时在加载弹窗&#xff0c;及有效的减少加载量&#xff0c;优化性能。 const handler …...

MySQL管理表

在创建表时需要提前了解mysql里面的数据类型 常见的数据类型 创建表 创建表方式1&#xff1a; 格式&#xff1a; CREATE TABLE [IF NOT EXISTS] 表名( 字段1, 数据类型 [约束条件] [默认值], 字段2, 数据类型 [约束条件] [默认值], 字段3, 数据类型 [约束条件] [默认值], ………...

【Java 面试合集】打印一个int整数的32位表示

打印一个int整数的32位表示 1. 概述 嗨&#xff0c;大家好【Java 面试合集】又来了&#xff0c;今天给大家分享的主题是打印一个int整数的32位表示. 2. 32位分析 2.1 为什么是32位呢 不知道看到这篇文章的各位是否都知道&#xff0c;一个int类型的表示方式就是32位呢&#x…...

这样在管理后台里实现 403 页面实在是太优雅了

前言403 页面通常表示无权限访问&#xff0c;与 404 页面代表着不同含义。而大部分管理后台框架仅提供了 404 页面的支持&#xff0c;但却忽略了对 403 页面的处理&#xff0c;有的框架虽然也有对 403 页面的处理&#xff0c;但处理效果却不尽人意。那怎么样的 403 页面才是即好…...

c++提高篇——STL常用算法

STL常用算法一、常用遍历算法一、for_each 遍历容器二、transform 搬运容器到另一个容器中二、常用查找算法一、find二、find_if三、adjacent_find四、binary_search五、count六、count_if三、常用排序算法一、sort二、random_shuffle三、 merage四、reverse四、常用拷贝和替换…...

Materials - DistanceField Nodes

以前的相关笔记&#xff0c;归档发布&#xff1b;距离场相关节点&#xff1a;DistanceToNearestSurface节点&#xff1a;求出传入的Position位置到最近的面的距离并输出&#xff0c;在没有Position输入的时候&#xff0c;默认值会直接使用World Position&#xff1a;Position的…...

【ARMv8 编程】ARMv8 指令集介绍

ARMv8 架构中引入的最重要的变化之一是增加了 64 位指令集。该指令集补充了现有的 32 位指令集架构。这种增加提供了对 64 位宽整数寄存器和数据操作的访问&#xff0c;以及使用 64 位长度的内存指针的能力。新指令被称为 A64&#xff0c;以 AArch64 执行状态执行。ARMv8 还包括…...

大数据之Phoenix基本介绍

文章目录前言一、Phoenix简介二、Phoenix入门&#xff08;一&#xff09;创建表语法&#xff08;二&#xff09;查看表信息&#xff08;三&#xff09;删除表&#xff08;四&#xff09;大小写问题前言 #博学谷IT学习技术支持# 上篇文章介绍了Phoenix环境搭建&#xff0c;点击…...

算法leetcode|38. 外观数列(多语言实现)

文章目录38. 外观数列&#xff1a;样例 1&#xff1a;样例 2&#xff1a;提示&#xff1a;分析&#xff1a;题解&#xff1a;rustgocpythonjava38. 外观数列&#xff1a; 给定一个正整数 n &#xff0c;输出外观数列的第 n 项。 「外观数列」是一个整数序列&#xff0c;从数字…...

异步交互的关键——Ajax

文章目录1,Ajax 概述1.1 作用1.2 同步和异步1.3 案例1.3.1 分析1.3.2 后端实现1.3.3 前端实现2&#xff0c;axios2.1 基本使用2.2 快速入门2.2.1 后端实现2.2.2 前端实现2.3 请求方法别名最后说一句1,Ajax 概述 AJAX (Asynchronous JavaScript And XML)&#xff1a;异步的 Jav…...

Android自定义View实现打钩签到动画

效果图实现原理我们看实现的动画效果&#xff0c;其实是分为1. 绘制未选中状态图形&#xff08;圆弧和对号&#xff09;2. 绘制选中状态圆弧的旋转的动画3. 绘制选中状态圆弧向中心收缩铺满动画4. 绘制选中状态对号5. 绘制选中状态下圆的放大回弹动画6. 暴露接口接口回调传递选…...

python+pytest接口自动化(3)-接口测试一般流程及方法

首先我们要明确&#xff0c;通常所接口测试其实就属于功能测试&#xff0c;主要校验接口是否实现预定的功能&#xff0c;虽然有些情况下可能还需要对接口进行性能测试、安全性测试。在学习接口自动化测试之前&#xff0c;我们先来了解手工接口测试怎样进行。URL组成为了更好的理…...

《MySQL学习》 表中随机取记录的方式

一.初始化测试表 创建表 words CREATE TABLE words ( id int(11) NOT NULL AUTO_INCREMENT, word varchar(64) DEFAULT NULL, PRIMARY KEY (id)) ENGINEInnoDB;插入测试数据 create procedure idata()begin declare i int; set i 0; while i<10000 do insert into words…...

建站工具交流/宁波seo公司推荐

先筛出来1000以内的素数。枚举x^(1/3) 和 y^(1/3)以内的素因子&#xff0c;这样除完以后对于x和y剩下的因子&#xff0c;小的那个的平方必须等于大的。然后判断每个素因数的次数之和是否为3的倍数&#xff0c;并且小的那个次数不小于大的次数的两倍。当然这题是有O&#xff08;…...

网站技术维护/网页在线代理翻墙

http://www.tuicool.com/articles/FRfMni2 http://docs.opencv.org/3.1.0/d7/d9f/tutorial_linux_install.html#gsc.tab0 http://blog.csdn.net/asongsongsong/article/details/52122504...

帝国cms调用网站地址/百度搜索软件

page1&#xff1a; 假设Server A上面有Process X&#xff0c;它有一个socket M&#xff0c;和另外的Server B上面的Process Y的 Socket N以TCP协议连接上了&#xff0c;那么&#xff0c;据我所知&#xff0c;有2种情况会出现RST包&#xff1a; &#xff08;1&#xff09;X没有c…...

企业网站推广的方法有( )/宁波网站seo哪家好

无论你是初学者还是经验丰富的开发人员&#xff0c;对于你和你的团队来说&#xff0c;提高异常处理的能力可以更好的解决问题。Java中的异常处理并不是一件容易的事&#xff0c;初学者会觉得很难理解&#xff0c;即使是经验丰富的开发人员也可能需要花费几个小时来讨论应该如何…...

网站建设价格请咨询兴田德润/怎么让关键词快速上首页

为什么80%的码农都做不了架构师&#xff1f;>>> 一、安装服务 本文以centos6.x系统为主在root用户或者具有root权限用户进行操作并且先改好主机名&#xff08;hostname&#xff09;&#xff0c;主要说明安装rabbitmq以及集群搭建关键性步骤. 1.准备工作去官方网站下…...

淄博高端网站建设/免费网页空间到哪申请

支付宝刚刚在官方微博上发表了一份致 236 位用户的道歉信&#xff0c;信中表示&#xff0c;在 7 月 26 日&#xff0c;“我们干了一件比较傻逼的事儿”&#xff0c;误向 236 位用户发送了中奖短信&#xff0c;为了弥补过错&#xff0c;支付宝将错就错&#xff0c;会负起责任向这…...