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

内置redis使用方法

在Spring Boot项目中,使用内置(嵌入式)Redis并通过注解实现缓存非常便捷。以下是具体实现步骤,主要利用Spring Cache抽象和嵌入式Redis的自动配置:

步骤1:引入依赖

pom.xml(Maven)或build.gradle(Gradle)中添加相关依赖,主要包括Spring Cache、嵌入式Redis和Redis客户端:

Maven依赖:

<!-- Spring Cache抽象 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId>
</dependency><!-- Redis客户端(Lettuce) -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency><!-- 嵌入式Redis(用于开发测试) -->
<dependency><groupId>it.ozimov</groupId><artifactId>embedded-redis</artifactId><version>0.7.3</version><scope>test</scope> <!-- 建议仅在测试环境启用 -->
</dependency>

说明embedded-redis默认是测试环境依赖,生产环境需切换为独立Redis。

步骤2:配置嵌入式Redis

application.yml中配置Redis和缓存相关参数,指定使用嵌入式Redis:

spring:cache:type: redis  # 缓存类型为Redisredis:time-to-live: 600000  # 缓存默认过期时间(10分钟,单位毫秒)cache-null-values: false  # 不缓存null值,避免缓存穿透use-key-prefix: true  # 使用缓存键前缀,防止键冲突redis:host: localhostport: 6379database: 0# 嵌入式Redis配置(仅在引入embedded-redis依赖时生效)embedded:enabled: true  # 启用嵌入式Redisport: 6379  # 嵌入式Redis端口(默认6379)

步骤3:启用缓存注解

在Spring Boot启动类上添加@EnableCaching注解,开启缓存功能:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;@SpringBootApplication
@EnableCaching  // 启用缓存注解
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}

步骤4:使用缓存注解

通过Spring提供的缓存注解(如@Cacheable@CachePut@CacheEvict)实现缓存逻辑,无需手动编写Redis操作代码。

示例Service层代码:
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;@Service
public class UserService {// 1. 查询数据时缓存:@Cacheable// 当调用该方法时,先查缓存;若缓存不存在,执行方法并将结果存入缓存@Cacheable(value = "userCache", key = "#id")  // value:缓存名称;key:缓存键(支持SpEL表达式)public User getUserById(Long id) {// 模拟数据库查询(实际中是DAO层调用)System.out.println("从数据库查询用户:" + id);return new User(id, "用户" + id, 20);}// 2. 更新数据时更新缓存:@CachePut// 执行方法后,将结果更新到缓存(适合新增/修改操作)@CachePut(value = "userCache", key = "#user.id")public User updateUser(User user) {// 模拟数据库更新System.out.println("更新数据库用户:" + user.getId());return user;}// 3. 删除数据时清除缓存:@CacheEvict// 执行方法后,删除指定缓存@CacheEvict(value = "userCache", key = "#id")public void deleteUser(Long id) {// 模拟数据库删除System.out.println("删除数据库用户:" + id);}// 4. 清除整个缓存(如批量删除场景)@CacheEvict(value = "userCache", allEntries = true)public void clearAllUsers() {// 模拟批量删除System.out.println("清空所有用户数据");}
}
实体类User:
import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class User {private Long id;private String name;private Integer age;
}

步骤5:测试缓存效果

编写Controller或测试类验证缓存是否生效:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/users")
public class UserController {@Autowiredprivate UserService userService;@GetMapping("/{id}")public User getUser(@PathVariable Long id) {return userService.getUserById(id);}@PutMappingpublic User updateUser(@RequestBody User user) {return userService.updateUser(user);}@DeleteMapping("/{id}")public String deleteUser(@PathVariable Long id) {userService.deleteUser(id);return "删除成功";}
}

测试现象

  • 首次调用/users/1:控制台输出“从数据库查询用户:1”(缓存未命中)。
  • 再次调用/users/1:控制台无输出(直接从缓存获取)。
  • 调用PUT /users更新用户:缓存会同步更新。
  • 调用DELETE /users/1:缓存中该用户数据会被清除。

核心注解说明

  1. @Cacheable:查询时缓存,优先从缓存获取,无缓存则执行方法并缓存结果。
  2. @CachePut:更新时同步缓存,执行方法后将结果存入缓存(常用于新增/修改)。
  3. @CacheEvict:删除时清除缓存,支持删除单个键(key)或整个缓存(allEntries = true)。
  4. @Caching:组合多个缓存操作(如同时更新和清除多个缓存)。

注意事项

  1. 环境区分:嵌入式Redis仅建议在开发/测试环境使用,生产环境需切换为独立Redis服务(只需移除embedded-redis依赖,配置独立Redis的hostport即可)。
  2. 缓存键生成:默认键生成策略为缓存名称::方法参数,可通过key属性自定义(使用SpEL表达式,如#user.id#root.methodName等)。
  3. 序列化方式:默认使用JDK序列化,可自定义为JSON(如Jackson2JsonRedisSerializer),避免序列化问题。
  4. 过期时间:通过spring.cache.redis.time-to-live设置全局过期时间,也可在@Cacheable中通过unless或自定义配置指定单个缓存的过期时间。

通过以上步骤,即可快速实现基于注解的嵌入式Redis缓存,简化开发流程的同时保证缓存逻辑的清晰性。


@EnableCaching 是 Spring 框架自带的注解(属于 org.springframework.cache.annotation 包),它的核心作用是开启 Spring 的缓存管理功能,底层已经内置了切面(AOP)处理逻辑,无需你手动实现切面。

具体说明:

  1. @EnableCaching 的作用
    该注解通过导入 CachingConfigurationSelector 类,自动注册了缓存相关的 AOP 切面(CacheInterceptor)和缓存管理器(CacheManager)。
    这些内置组件会拦截被 @Cacheable@CachePut 等注解标记的方法,在方法执行前后自动完成缓存的查询、更新、删除等操作,完全无需你手动编写切面代码。

  2. 无需手动处理切面的原因
    Spring 缓存抽象的设计理念是**“声明式缓存”**:

    • 你只需通过注解(@Cacheable 等)声明“哪些方法需要缓存”“缓存规则是什么”,底层的 AOP 逻辑由 Spring 自动实现。
    • 切面会在方法执行前检查缓存是否存在,存在则直接返回缓存结果(跳过方法执行);不存在则执行方法,再将结果存入缓存(对应 @Cacheable)。
    • 对于 @CachePut @CacheEvict 等注解,切面会在方法执行后自动触发缓存更新或清除操作。
  3. 自定义扩展的可能性
    虽然无需手动写切面,但你可以通过以下方式自定义缓存行为:

    • 自定义 KeyGenerator 改变缓存键的生成规则;
    • 自定义 CacheManager 配置缓存的序列化方式、过期时间等;
    • 实现 Cache 接口扩展自定义缓存逻辑(如结合 Redis 高级特性)。

总结:

@EnableCaching 是 Spring 自带的注解,已内置切面处理逻辑,你只需在启动类上添加该注解,并在方法上使用 @Cacheable 等注解,即可实现缓存功能,无需手动编写 AOP 切面代码。这种声明式设计极大简化了缓存集成的复杂度。





要理解@Async的作用和优势,我们可以从“同步执行”的问题入手,对比来看异步的价值。

一、先看“同步执行”的痛点

假设你有一个接口,需要完成3件事:

  1. 保存用户数据到数据库(耗时50ms)
  2. 发送欢迎邮件给用户(耗时1000ms,因为涉及网络请求)
  3. 记录操作日志到文件(耗时20ms)

如果用同步执行(默认方式),代码会按顺序执行:

public void register(User user) {saveToDB(user);       // 50mssendEmail(user);      // 1000ms(耗时最长)logOperation(user);   // 20ms
}

总耗时 = 50 + 1000 + 20 = 1070ms
此时,用户会感受到明显的卡顿(超过1秒),因为必须等所有步骤完成才能得到响应。

二、@Async的作用:让任务“并行执行”

@Async标记耗时的步骤(如发送邮件),让它在独立线程中执行,不阻塞主线程:

public void register(User user) {saveToDB(user);       // 主线程执行(50ms)asyncSendEmail(user); // 异步执行(扔给线程池,不等待)logOperation(user);   // 主线程继续执行(20ms)
}@Async // 异步方法:在独立线程中执行
public void asyncSendEmail(User user) {sendEmail(user); // 1000ms(在其他线程执行)
}

总耗时 ≈ 50 + 20 = 70ms
主线程只需执行快速任务(存数据库、打日志),耗时操作(发邮件)在后台线程跑,用户几乎感觉不到卡顿。

三、异步的核心优势

  1. 提升用户体验
    避免用户等待耗时操作(如邮件、短信、文件上传),接口响应速度大幅提升(从秒级到毫秒级)。

  2. 提高系统吞吐量
    同步执行时,一个请求会占用线程直到完成,高并发下线程会被耗尽(如1000个请求同时发邮件,线程全被阻塞)。
    异步执行时,主线程快速释放,可处理更多请求,而耗时操作由线程池统一管理,资源利用率更高。

  3. 解耦操作步骤
    非核心流程(如日志、统计)可异步执行,不影响核心业务(如订单提交),即使异步操作失败,也不会导致主流程出错。

四、哪些场景必须用异步?

  1. 耗时的IO操作

    • 发送邮件/短信(调用第三方API,网络耗时)
    • 文件上传下载(磁盘IO耗时)
    • 调用外部接口(如支付回调、数据同步)
  2. 非实时必要的操作

    • 日志记录、数据统计(用户不需要等待这些完成)
    • 消息通知(如“订单已发货”,晚几秒发送不影响)
  3. 高并发场景

    • 秒杀、抢购(必须快速响应,后续逻辑异步处理)
    • 批量处理(如批量导出数据,前端先返回“处理中”,后端异步执行)

总结

@Async的本质是**“让耗时操作在后台偷偷跑,不耽误主线程干活”**。
它解决了同步执行时“一人干活、大家等待”的问题,通过多线程并行处理,显著提升系统的响应速度和并发能力,是处理高并发、优化用户体验的核心手段之一。

http://www.lryc.cn/news/617677.html

相关文章:

  • Python 高阶函数:filter、map、reduce 详解
  • 【软考架构】主流数据持久化技术框架
  • Spring Boot Excel数据导入数据库实现详解
  • 6s081实验1
  • 机器翻译:一文掌握序列到序列(Seq2Seq)模型(包括手写Seq2Seq模型)
  • 机器学习TF-IDF算法详解
  • GPT-oss:OpenAI再次开源新模型,技术报告解读
  • 视频播放器哪个好用?视频播放器PotPlayer,KMP Player
  • FPGA学习笔记——DS18B20(数字温度传感器)
  • Mysql系列--6、内置函数
  • C++的结构体传参
  • 深度学习与遥感入门(五)|GAT 构图消融 + 分块全图预测:更稳更快的高光谱图分类(PyTorch Geometric 实战)
  • rust编译过程的中间表现形式如何查看,ast,hir,mir
  • Rust 实战五 | 配置 Tauri 应用图标及解决 exe 被识别为威胁的问题
  • istio如何采集method、url指标
  • Rust:anyhow 高效错误处理库核心用法详解
  • Elasticsearch 官方 Node.js 从零到生产
  • 用 Node.js 玩转 Elasticsearch从安装到增删改查
  • 基于动态顺序表实现【通讯录系统】:有文件操作部分哦!
  • 用 Docker 安装并启动 Redis:从入门到实战
  • Spring AI赋能图像识别:大数据模型驱动下的智能化变革
  • Webpack Loader 完全指南:从原理到配置的深度解析
  • 关于JavaScript 性能优化的实战指南
  • MySQL的索引(索引的数据结构-B+树索引):
  • Godot ------ 平滑拖动01
  • vue3中的子组件向父组件通信和父组件向子组件通信
  • 对抗样本攻击检测与防御
  • STM32 ESP8266 WiFi模块驱动
  • JVM管理数据的方式
  • CV 医学影像分类、分割、目标检测,之分类项目拆解