重学SpringBoot3-集成Redis(二)之注解驱动

更多SpringBoot3内容请关注我的专栏:《SpringBoot3》
期待您的点赞👍收藏⭐评论✍

重学SpringBoot3-集成Redis(二)之注解驱动

  • 1. 为什么选择 Redis 作为缓存?
  • 2. 如何在 Spring Boot 中启用 Redis 缓存?
    • 2.1 添加 Redis 依赖
    • 2.2 配置 Redis 连接
    • 2.3 启用缓存支持
  • 3. 注解驱动的缓存机制
    • 3.1 @Cacheable示例
    • 3.2 @CachePut示例
    • 3.3 @CacheEvict示例
  • 4. 自定义缓存管理
    • 4.1 RedisCacheConfiguration 类
      • 4.1.1. 过期时间(TTL - Time To Live)
      • 4.1.2. 键序列化方式
      • 4.1.3. 值序列化方式
      • 4.1.4. 禁用缓存空值(Disable Caching Null Values)
      • 4.1.5. 使用前缀(Use Cache Key Prefixes)
      • 4.1.6. 设置空闲时间(Idle Time)
      • 4.1.7. 组合多种配置
      • 4.1.8. 设置自定义的过期策略
    • 4.2 自定义缓存配置
  • 5. Redis 缓存的常见问题和优化建议
  • 6. 总结

Spring Boot 提供了对缓存的简便支持,使得开发者能够通过简单的注解实现缓存操作,减少重复代码的编写。本文将详细介绍如何在 Spring Boot 3 中使用 Redis 作为缓存,并通过注解驱动的方式进行缓存操作。

1. 为什么选择 Redis 作为缓存?

Redis 是一个高效的键值对存储系统,特别适合于构建高性能、可扩展的缓存层。其优点包括:

  • 高吞吐量:Redis 使用内存作为存储介质,读取和写入性能极快,能够支撑高并发的访问需求。
  • 数据持久化:尽管 Redis 是内存数据库,它也支持将数据持久化到磁盘,防止数据丢失。
  • 丰富的数据结构:Redis 不仅支持简单的字符串存储,还支持哈希、列表、集合等丰富的数据结构,适用于多种应用场景。
  • 易于扩展:通过 Redis 的集群功能,可以很容易地扩展 Redis 实例,处理更大规模的数据和请求。

2. 如何在 Spring Boot 中启用 Redis 缓存?

Spring Boot 提供了对缓存的开箱即用支持,开发者只需简单配置即可使用。具体参考上一章 重学SpringBoot3-集成Redis(一)。

2.1 添加 Redis 依赖

pom.xml 中引入 Redis 和 Spring Cache 相关依赖:

        <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.2 配置 Redis 连接

application.yml 中,配置 Redis 服务器地址及相关连接池配置:

spring:cache:type: redis     	 	# 使用 Redis 作为缓存类型data:redis:host: localhostport: 6379            # Redis 端口password: 			# 如果有密码可以在这里配置lettuce:pool:max-active: 100    # 最大并发连接数max-idle: 50       # 最大空闲连接数min-idle: 10       # 最小空闲连接数

2.3 启用缓存支持

在 Spring Boot 项目中,使用 @Cacheable 注解前,需要通过 @EnableCaching 注解启用缓存功能。可以在主应用类或者任何配置类中加上这个注解:

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
@EnableCaching
public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);}
}

3. 注解驱动的缓存机制

Spring 提供了一组注解用于操作缓存,这些注解可以直接应用于方法上,使得代码更简洁。常用注解包括:

  • @Cacheable:用于标记一个方法的返回值是可缓存的。下一次调用该方法时,Spring 会直接从缓存中返回结果,而不是再次执行方法。
  • @CachePut:在方法执行后将返回值放入缓存。它与 @Cacheable 的区别在于,@CachePut 不会跳过方法执行,而是始终执行方法并更新缓存。
  • @CacheEvict:用于清除缓存中的某些条目,可以指定缓存的 key 或清空整个缓存空间。

3.1 @Cacheable示例

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;@Service
public class UserService {// 当方法第一次调用时,结果将被缓存起来,之后相同参数的调用将直接从缓存中获取数据@Cacheable(value = "user", key = "#p0")public User getUserById(Long id) {// 模拟数据库查询操作System.out.println("Fetching user with id: " + id);return new User(id, "User" + id);}
}

解释:

  • @Cacheable 用于缓存方法的返回值。
  • value = "user" 指定了缓存的名称,即 “user”。
  • key = "#p0" 指定了缓存的键值。这里的 #p0 是一个 SpEL 表达式,表示方法的第一个参数。

在这个例子中,方法 getUserById 第一次被调用时,结果会缓存到 Redis 中,并与 user::id 作为 key 存储。后续相同 id 的请求将直接从缓存返回,而无需执行方法。

@Cacheable添加缓存

3.2 @CachePut示例

有时候,我们希望方法执行后,不仅返回结果,还更新缓存,这时可以使用 @CachePut 注解。

import org.springframework.cache.annotation.CachePut;
import org.springframework.stereotype.Service;@Service
public class UserService {// 无论缓存中是否存在数据,该方法都会被执行,并且返回值会更新缓存@CachePut(value = "user", key = "#p0.id")public User updateUser(User user) {System.out.println("Updating user with id: " + user.getId());// 模拟数据库更新操作user.setName("Updated " + user.getName());return user;}
}

解释:

  • @CachePut 用于更新缓存中的值。
  • value = "user" 指定了缓存的名称,即 “user”。
  • key = "#p0.id" 指定了缓存的键值。这里的 #p0 是一个 SpEL 表达式,表示方法的第一个参数,即 User 对象。.id 表示取 User 对象的 id 属性作为缓存键。

连续两次调用 curl "http://localhost:8080/api/redis/updAndSave?id=2" ,可以从日志中看到,每次方法都执行了,并且 user 对象加入到了缓存中。

@CachePut更新缓存

3.3 @CacheEvict示例

为了保持缓存数据的准确性,某些情况下需要手动清除缓存中的数据。@CacheEvict 注解允许我们在数据修改或删除时,移除缓存中的旧数据。

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;@Service
public class UserService {// 清除缓存中的指定用户数据@CacheEvict(value = "user", key = "#p0")public void deleteUser(Long id) {System.out.println("Deleting user with id: " + id);// 模拟数据库删除操作}// 清空整个缓存空间@CacheEvict(value = "user", allEntries = true)public void clearCache() {System.out.println("Clearing all user cache");}
}

调用 curl "http://localhost:8080/api/redis/delUser?id=1" ,删除 key 为 user::1 的缓存。

@CacheEvict删除缓存

调用 curl "http://localhost:8080/api/redis/delAllUser" ,删除所有前缀为 user:: 的缓存。

@CacheEvict删除所有缓存

4. 自定义缓存管理

以上缓存名称、过期时间和序列化方式都是默认设置,Spring 允许我们自定义缓存管理器。在大多数情况下,默认配置足够使用,但如果需要定制化的缓存行为,我们可以自定义缓存配置。通过实现 RedisCacheConfiguration,我们可以设置缓存的过期时间、序列化方式等。

4.1 RedisCacheConfiguration 类

Spring Boot 3 中,RedisCacheConfiguration 类是用于配置 Redis 缓存行为的核心组件之一。它提供了多种方法,用于自定义 Redis 缓存的各类设置,比如缓存过期时间、序列化策略等。以下是一些常用的配置选项:

4.1.1. 过期时间(TTL - Time To Live)

设置缓存条目的默认生存时间(TTL)。这决定了缓存数据在 Redis 中保留的时间。

RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10)); // 设置缓存10分钟后过期

4.1.2. 键序列化方式

默认情况下,Redis 使用二进制存储键和值。RedisCacheConfiguration 提供了设置键(key)序列化方式的方法。常见的序列化方式包括 StringRedisSerializer,可以使用它来确保键以字符串格式存储:

import org.springframework.data.redis.serializer.StringRedisSerializer;RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));

4.1.3. 值序列化方式

同样,值(value)的序列化方式也可以自定义。常用的序列化方式有 GenericJackson2JsonRedisSerializer,它将对象序列化为 JSON 格式:

import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));

4.1.4. 禁用缓存空值(Disable Caching Null Values)

你可以配置不缓存空值,避免 Redis 存储 null,减少缓存的无效占用。

RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().disableCachingNullValues();

4.1.5. 使用前缀(Use Cache Key Prefixes)

Redis 中默认会为缓存键值加上一个命名空间的前缀,以防止不同缓存键冲突。可以自定义这个前缀,也可以关闭它:

RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().prefixCacheNameWith("myApp::")  // 自定义缓存键前缀.computePrefixWith(cacheName -> "customPrefix::" + cacheName + "::");  // 使用自定义逻辑

要禁用前缀:

RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().disableKeyPrefix();

4.1.6. 设置空闲时间(Idle Time)

你可以设置一个键的空闲时间,Redis 将会在指定的时间内删除不再被访问的键。

RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10)).enableTimeToIdle();

4.1.7. 组合多种配置

可以将多个配置组合到一起:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;import java.time.Duration;@Configuration
public class CacheConfig {@Beanpublic RedisCacheConfiguration redisCacheConfiguration() {return RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10))  // 缓存的过期时间.disableCachingNullValues()        // 不缓存 null 值.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))  // 自定义 key 序列化.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); // 自定义 value 序列化}
}

4.1.8. 设置自定义的过期策略

可以为不同的缓存区域设置不同的过期策略。例如:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;@Configuration
public class CacheConfig {@Beanpublic RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {RedisCacheConfiguration defaultConfig = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(5));RedisCacheConfiguration longLivedConfig = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(1));Map<String, RedisCacheConfiguration> cacheConfigurations = new HashMap<>();cacheConfigurations.put("shortLivedCache", defaultConfig);cacheConfigurations.put("longLivedCache", longLivedConfig);return RedisCacheManager.builder(connectionFactory).withInitialCacheConfigurations(cacheConfigurations).build();}
}

4.2 自定义缓存配置

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;import java.time.Duration;@Configuration
public class CacheConfig {@Beanpublic RedisCacheConfiguration cacheConfiguration() {return RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10))  // 设置缓存过期时间为 10 分钟.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) // 自定义 Key 序列化器.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())); // 自定义 Value 序列化器}
}

通过这种方式,我们可以对缓存的过期时间、序列化方式进行更细粒度的控制。

自定义配置

5. Redis 缓存的常见问题和优化建议

尽管 Redis 是一个高效的缓存解决方案,但在实际应用中,仍然有一些需要注意的问题:

  • 缓存穿透:大量请求查询缓存中不存在的 key,导致所有请求都直接打到数据库上,降低系统性能。解决方案是使用布隆过滤器来拦截非法请求。
  • 缓存雪崩:当大量缓存同时过期时,可能会导致瞬间的大量请求直接涌入数据库,造成系统崩溃。可以通过设置不同的过期时间(TTL)来缓解这一问题。
  • 缓存击穿:某个热点 key 在缓存过期后,大量并发请求直接打到数据库上。解决方案是使用互斥锁,避免大量请求同时加载缓存。

6. 总结

通过本文,我们学习了如何在 Spring Boot 3Java 17 中使用 Redis 作为缓存。Spring 提供了注解驱动的缓存操作方式,使得缓存操作变得非常简单易用。通过合理配置和使用缓存,我们能够极大地提升系统的性能和响应速度。在生产环境中,合理的缓存策略、过期时间和缓存层优化将会进一步提高系统的稳定性和扩展能力。

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

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

相关文章

华为OD七日集训第1期 - 按算法分类,由易到难,循序渐进,玩转OD(Python/JS/C/C++)

目录 一、适合人群二、本期训练时间三、如何参加四、7日集训五、精心挑选21道高频100分经典题目&#xff0c;作为入门。第1天、逻辑分析第2天、数组第3天、双指针第4天、滑动窗口第5天、贪心算法第6天、二分查找第7天、分治递归 六、集训总结 大家好&#xff0c;我是哪吒。 最…

Qt程序打包(解决找到dll问题)

1、运行Qt程序找不到dll 在Qt Creator外&#xff0c;运行Qt编译的exe程序&#xff0c;常常出现找不到xxx.dll而无法运行的问题。 解决的办法之一是找到Qt安装目录下bin文件夹中的dll文件&#xff0c;将该路径添加到系统环境变量path中去。 第二种办法就是对Qt程序进行打包&…

来了,使用YOLOv11目标检测教程

来了&#xff0c;使用YOLOv11目标检测教程 概述 YOLO11 在 2024 年 9 月 27 日的 YOLO Vision 2024 活动中宣布&#xff1a;https://www.youtube.com/watch?vrfI5vOo3-_A。 YOLO11 是 Ultralytics YOLO 系列的最新版本&#xff0c;结合了尖端的准确性、速度和效率&#xff…

【LeetCode】动态规划—72. 编辑距离(附完整Python/C++代码)

动态规划—72. 编辑距离 前言题目描述基本思路1. 问题定义2. 理解问题和递推关系3. 解决方法3.1 动态规划方法3.2 空间优化的动态规划 4. 进一步优化5. 小总结 代码实现PythonPython3代码实现Python 代码解释 CC代码实现C 代码解释 总结: 前言 编辑距离问题是字符串处理中的经…

threejs-模型贴图颜色与图片存在色差 问题解决方案

我使用的是obj模型&#xff0c;然后加载的话使用的是texturelLoader加载器&#xff0c;效果是这样的 使用的场景是&#xff1a;能够将图片贴到衣服上&#xff0c;并且能够移动旋转等操作贴图&#xff0c;但是这存在很明显的色差问题&#xff0c;具体的解决方案是&#xff1a; 我…

.Net Core 接口或网站发布到IIS

将.Net Core 接口或网站发布到IIS上&#xff0c;需要遵循一系列步骤来确保正确配置和部署。下面将以.NET Core 3.1的api接口发布示范&#xff1a; 一、环境准备 安装.NET Core 3.1 SDK和运行时&#xff1a; 在服务器上安装.NET Core 3.1 SDK&#xff08;如果需要在服务器上编译…

LeetCode 48 Rotate Image 解题思路和python代码

题目&#xff1a; You are given an n x n 2D matrix representing an image, rotate the image by 90 degrees (clockwise). You have to rotate the image in-place, which means you have to modify the input 2D matrix directly. DO NOT allocate another 2D matrix and …

桥水基金、贝莱德、摩根士丹利选择极狐GitLab 的五大理由!

疯狂上涨的 A股、港股 节前一周&#xff0c;上证指数累计上涨超 12%&#xff0c;创下2008年11月以来最大单周涨幅&#xff1b;深证成指累计上涨超17%&#xff0c;创下1996年4月最大单周涨幅&#xff1b;创业板指上涨超22%&#xff0c;创下史上最大单周涨幅。 过去两周&#x…

1688代采系统-反向海淘系统详细介绍

Onebound凡邦1688代采系统-反向海淘系统是一种专为海外买家及跨境电商提供一站式采购解决方案的平台。其核心功能和服务旨在解决跨境采购中的语言、货币等常见问题&#xff0c;并优化采购流程&#xff0c;提高采购效率。以下是对该系统的详细介绍。 一、核心功能 商品采集与展…

基于Java(Jsp+Sevlet)+MySql 实现的(Web)成绩管理系统

1 概述 1.1 开发背景 随着学生数量的日渐增多&#xff0c;学生教务系统的数据量也不断增加&#xff0c;这无疑大大增加了教务系统的负担。如果能把负责学生成绩管理的模块独立出来形成一个独立的系统&#xff0c;便可以有效降低教务系统的数据量&#xff0c;不仅可以方便管理…

2003-2023年上市公司政府补助明细数据

2003-2023年上市公司政府补助明细数据 1、时间&#xff1a;2003-2023年 2、来源&#xff1a;通过整理和筛选于企业财务报表附注“营业外收入”下的“政府补助明细”得到 3、指标&#xff1a;年份、股票代码、股票简称、行业名称、省份、城市、区县、上市状态、政府补助金额、…

企业架构系列(16)ArchiMate第14节:实施和迁移视角

在企业架构中&#xff0c;为了有效地规划和管理架构的变更与实施&#xff0c;通常会使用不同的视角来描述架构的不同方面。本篇涉及到三个主要视角&#xff1a;项目视角、迁移视角以及实施与迁移视角。 一、实施和迁移视角概览 1.项目视角 元素与关系&#xff1a;关注项目本身…

基于ResNet50模型的船型识别与分类系统研究

关于深度实战社区 我们是一个深度学习领域的独立工作室。团队成员有&#xff1a;中科大硕士、纽约大学硕士、浙江大学硕士、华东理工博士等&#xff0c;曾在腾讯、百度、德勤等担任算法工程师/产品经理。全网20多万粉丝&#xff0c;拥有2篇国家级人工智能发明专利。 社区特色…

获取时隔半个钟的三天

摘要&#xff1a; 今天遇到需求是配送时间&#xff0c;时隔半个钟的排线&#xff01;所以需要拼接时间&#xff01;例如2024-10-08 14&#xff1a;30&#xff0c;2024-10-08 15&#xff1a;00&#xff0c;2024-10-08 15&#xff1a;30 <el-form-item label"配送时间&a…

AP8505固定5V输出5V0.2A,SOP7/DIP7非隔离开关电源IC

AP8505基于高压同步整流架构&#xff0c;集成PFM控制器以及500V高可靠性MOSFET&#xff0c;用于外部元器件极精简的小功率非隔离开关电源。AP8505无线门铃芯片内置500V高压启动&#xff0c;实现系统快速启动、超低待机功能。5V非隔离无线门铃芯片AP8505提供了完整的智能化保护功…

海报制作用什么软件?快速搞定年末各种节日借势海报设计

厌倦了自己动手从零开始做宣传海报&#xff1f; 想要找AI智能工具&#xff0c;却又觉得生成的图片太假&#xff0c;不够的宣传格调&#xff1f; 想要找海报制作模板免费下载的平台&#xff0c;还总找不到自己想要的那一个风格的模板&#xff1f; 有没有想过&#xff0c;是你…

fastdfs下的doc文件可以访问,但是图片无法访问报错404,解决记录

fastdfs下的doc文件可以访问,但是图片无法访问报错404 以下内容主要讲linux的问题 以下内容主要讲linux的问题 以下内容主要讲linux的问题 以下内容主要讲linux的问题 以下内容主要讲linux的问题 第1项:查看Nginx的日志 可以先去查看Nginx的日志,在你Nginx的安装目录下的lo…

N1从安卓盒子刷成armbian

Release Armbian_noble_save_2024.10 ophub/amlogic-s9xxx-armbian (github.com) armbian下载&#xff0c;这里要选择905d adb 下载地址 https://dl.google.com/android/repository/platform-tools-latest-windows.zip 提示信息 恩山无线论坛 使用usb image tool restet a…

探索创新宝库:一站式免费专利检索工具揭秘!

在这个知识爆炸的时代&#xff0c;专利不仅是创新成果的保护伞&#xff0c;更是技术发展的指南针。对于研究者、发明家、企业乃至普通爱好者&#xff0c;专利检索成为了探索技术前沿、规避侵权风险、激发创新灵感的重要手段。今天&#xff0c;我们将带您了解一款集多功能于一身…

第七在线7thonline荣耀加冕 斩获“最佳数据洞察平台”与“产业互联网最具发展潜力企业”两项大奖!

在科技创新与数字化转型的浪潮中&#xff0c;7thonline第七在线再次以卓越的技术实力和深厚的行业积累&#xff0c;赢得了业界的广泛认可&#xff0c;一举斩获“最佳数据洞察平台“和“产业互联网最具发展潜力企业”两项大奖。 01、“最佳数据洞察平台” “Ai新智奖”是国内首个…