news 2026/5/2 16:59:21

《Spring Boot 集成 Redis 完整教程:从配置到缓存实战(附源码)》

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
《Spring Boot 集成 Redis 完整教程:从配置到缓存实战(附源码)》

一、前言

在分布式系统开发中,缓存是提升接口响应速度、减轻数据库压力的关键手段。Redis 作为高性能的键值对数据库,凭借其支持多种数据结构、读写速度快、可持久化等特性,成为 Spring Boot 项目的首选缓存方案。本文将从环境准备、依赖配置、代码实现、缓存策略优化四个维度,带大家从零实现 Spring Boot 与 Redis 的无缝集成,附完整代码示例和常见问题解决方案。

二、环境准备

1. 基础环境
  • JDK 1.8+
  • Spring Boot 2.7.x(兼容 2.x 版本,3.x 版本配置略有差异)
  • Redis 6.2.x(本地或云服务器部署均可)
  • Maven 3.6+
2. Redis 环境验证

确保 Redis 服务正常启动,可通过以下命令测试连接:

# 本地 Redis 连接

redis-cli -h 127.0.0.1 -p 6379

# 输入 ping,返回 PONG 则表示连接正常

127.0.0.1:6379> ping

PONG

三、核心配置步骤

1. 引入 Maven 依赖

在 pom.xml 中添加 Spring Boot 整合 Redis 的核心依赖,无需额外引入 Redis 客户端(Spring Boot 自动适配 Lettuce 客户端):

Redis starter -->

<dependency>

>org.springframework.boot

-boot-starter-data-redis</artifactId>

>

依赖(Lettuce 底层依赖 commons-pool2) -->

>

.apache.commons ool2</dependency>

2. 配置 application.yml

在配置文件中添加 Redis 连接信息、连接池配置和缓存通用配置:

spring:

# Redis 配置

redis:

host: 127.0.0.1 # Redis 服务器地址

port: 6379 # 端口号

password: "" # 若未设置密码则留空

database: 0 # 操作的数据库索引(默认 0)

# Lettuce 连接池配置

lettuce:

pool:

max-active: 8 # 最大连接数

max-idle: 8 # 最大空闲连接数

min-idle: 2 # 最小空闲连接数

max-wait: -1ms # 最大等待时间(-1 表示无限制)

# 缓存通用配置

cache:

type: redis # 缓存类型为 Redis

redis:

time-to-live: 3600000ms # 缓存默认过期时间(1 小时)

cache-null-values: false # 是否缓存 null 值(避免缓存穿透)

use-key-prefix: true # 是否使用缓存前缀(默认前缀为 cache:)

3. 自定义 Redis 配置类

Spring Boot 自动配置的 RedisTemplate 序列化方式为 JDK 序列化,存在可读性差、占用空间大的问题。我们通过自定义配置类,将序列化方式改为 JSON 格式:

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.cache.RedisCacheManager;

import org.springframework.data.redis.connection.RedisConnectionFactory;

import org.springframework.data.redis.core.RedisTemplate;

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

@EnableCaching // 开启缓存注解支持

public class RedisConfig {

/**

* 自定义 RedisTemplate:解决默认序列化问题

*/

@Bean

public RedisTemplate, Object> redisTemplate(RedisConnectionFactory factory) {

RedisTemplate, Object> template = new RedisTemplate template.setConnectionFactory(factory);

// 字符串序列化器(key 采用 String 序列化)

StringRedisSerializer stringSerializer = new StringRedisSerializer();

template.setKeySerializer(stringSerializer);

template.setHashKeySerializer(stringSerializer);

// JSON 序列化器(value 采用 JSON 序列化)

GenericJackson2JsonRedisSerializer jsonSerializer = new GenericJackson2JsonRedisSerializer();

template.setValueSerializer(jsonSerializer);

template.setHashValueSerializer(jsonSerializer);

// 初始化模板

template.afterPropertiesSet();

return template;

}

/**

* 自定义 RedisCacheManager:统一缓存配置

*/

@Bean

public RedisCacheManager cacheManager(RedisConnectionFactory factory) {

// 缓存配置:JSON 序列化 + 过期时间

RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()

.entryTtl(Duration.hours(1)) // 默认过期时间 1 小时

.serializeKeysWith(RedisSerializationContext.SerializationPair

.fromSerializer(new StringRedisSerializer())) // key 序列化

.serializeValuesWith(RedisSerializationContext.SerializationPair

.fromSerializer(new GenericJackson2JsonRedisSerializer())) // value 序列化

.disableCachingNullValues(); // 不缓存 null 值

// 构建缓存管理器

return RedisCacheManager.builder(factory)

.cacheDefaults(config)

.build();

}

}

四、实战:缓存注解的使用

1. 实体类准备

创建用户实体类(需实现序列化接口,或使用 JSON 序列化时无需显式实现):

import lombok.Data;

@Data

public class User {

private Long id;

private String username;

private String phone;

private Integer age;

}

2. Service 层缓存实现

通过 @Cacheable、@CachePut、@CacheEvict 三个核心注解实现缓存的增删改查:

import org.springframework.cache.annotation.CacheEvict;

import org.springframework.cache.annotation.CachePut;

import org.springframework.cache.annotation.Cacheable;

import org.springframework.stereotype.Service;

import java.util.HashMap;

import java.util.Map;

@Service

public class UserService {

// 模拟数据库存储

private static final Map> USER_DB = new HashMap<>();

static {

// 初始化测试数据

USER_DB.put(1L, new User(1L, "张三", "13800138000", 25));

USER_DB.put(2L, new User(2L, "李四", "13900139000", 30));

}

/**

* 查询用户:缓存存在则返回缓存数据,不存在则执行方法并缓存结果

* key:缓存键(默认使用方法参数作为 key,这里显式指定为 user::id)

*/

@Cacheable(value = "user", key = "#id", unless = "#result == null")

public User getUserById(Long id) {

System.out.println("===== 执行数据库查询,id:" + id + " =====");

return USER_DB.get(id);

}

/**

* 更新用户:执行方法后,更新缓存(覆盖原缓存)

*/

@CachePut(value = "user", key = "#user.id")

public User updateUser(User user) {

System.out.println("===== 执行数据库更新,id:" + user.getId() + " =====");

USER_DB.put(user.getId(), user);

return user;

}

/**

* 删除用户:执行方法后,删除对应缓存

*/

@CacheEvict(value = "user", key = "#id")

public void deleteUser(Long id) {

System.out.println("===== 执行数据库删除,id:" + id + " =====");

USER_DB.remove(id);

}

}

3. 测试接口(Controller 层)

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.*;

@RestController

@RequestMapping("/user")

public class UserController {

@Autowired

private UserService userService;

@GetMapping("/{id}")

public User getUser(@PathVariable Long id) {

return userService.getUserById(id);

}

@PutMapping

public User updateUser(@RequestBody User user) {

return userService.updateUser(user);

}

@DeleteMapping("/{id}")

public String deleteUser(@PathVariable Long id) {

userService.deleteUser(id);

return "删除成功";

}

}

五、缓存优化与避坑指南

1. 缓存穿透问题解决
  • 原因:查询不存在的 key 时,缓存未命中,导致频繁访问数据库。
  • 解决方案:
    1. 配置 cache-null-values: true(缓存 null 值,过期时间设为 5-10 分钟);
    1. 接口层增加参数校验,过滤无效 id(如小于 1 的 id)。
2. 缓存击穿问题解决
  • 原因:热点 key 过期瞬间,大量请求同时访问数据库。
  • 解决方案:
    1. 热点 key 设置永不过期(或超长过期时间);
    1. 使用互斥锁(如 Redis 的 SETNX),确保同一时间只有一个请求更新缓存。
3. 缓存雪崩问题解决
  • 原因:大量缓存 key 同时过期,导致数据库压力骤增。
  • 解决方案:
    1. 缓存过期时间添加随机值(如 time-to-live: ${random.int[3600000, 7200000]}ms);
    1. 核心业务缓存集群部署,避免单点故障。
4. 序列化问题注意事项
  • 避免使用 JDK 序列化:可读性差、占用空间大,优先使用 JSON 序列化;
  • 实体类若使用 Lombok,需确保有无参构造函数(JSON 反序列化依赖);
  • 若实体类属性有新增 / 删除,建议清理旧缓存,避免反序列化失败。

六、总结

本文详细介绍了 Spring Boot 集成 Redis 的完整流程,从环境搭建、配置优化到实战应用,覆盖了缓存注解的核心使用场景和常见问题解决方案。通过 Redis 缓存,可显著提升接口响应速度(毫秒级响应),尤其适用于高频查询、数据变更较少的场景(如用户信息、商品详情等)。

后续可进一步探索 Redis 的高级特性,如分布式锁、消息队列、地理位置存储等,欢迎在评论区交流探讨!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/20 22:21:01

EmotiVoice vs 其他TTS:谁才是真正的多情感之王?

EmotiVoice vs 其他TTS&#xff1a;谁才是真正的多情感之王&#xff1f; 在虚拟主播直播带货时突然“哽咽”&#xff0c;游戏NPC被攻击后语气从平静转为暴怒&#xff0c;有声书朗读到悲剧情节时声音微微颤抖——这些曾属于人类专属的情感表达&#xff0c;如今正被AI语音悄然复现…

作者头像 李华
网站建设 2026/5/1 1:21:01

微信封杀豆包,阿里系APP跟进,背后到底怕什么?

2025年12月&#xff0c;豆包手机正式发布&#xff0c;凭借其革命性的AI技术和深度集成的智能助手系统&#xff0c;迅速吸引了大量科技爱好者的目光。然而&#xff0c;豆包手机的成功并未获得市场的完全接纳。相反&#xff0c;它遭遇了 微信 和 阿里系应用 的集体封杀&#xff0…

作者头像 李华
网站建设 2026/4/29 12:38:07

【spring源码】从废弃的XmlBeanFactory到XmlBeanDefinitionReader

从废弃的XmlBeanFactory到XmlBeanDefinitionReader 统一术语 在开始之前&#xff0c;我们先明确几个关键术语&#xff1a; BeanFactory&#xff1a;Spring 容器的基础接口&#xff0c;负责 Bean 的创建、管理和获取BeanDefinition&#xff1a;Bean 的定义信息&#xff0c;包…

作者头像 李华
网站建设 2026/4/23 18:37:41

Linux下创建线程:从入门到实践

&#x1f427; Linux下创建线程&#xff1a;从入门到实践 &#x1f4da; 线程基础概念&#x1f527; Linux线程创建方法1. 基本线程创建2. 带参数的线程 ⚙️ 线程属性设置&#x1f504; 线程同步机制1. 互斥锁&#xff08;Mutex&#xff09;2. 条件变量&#xff08;Condition …

作者头像 李华
网站建设 2026/4/29 17:33:27

《网络数据安全风险评估办法》出台在即,CCRC-DSA成关键人才!

随着国家互联网信息办公室在2025年12月发布《网络数据安全风险评估办法&#xff08;征求意见稿&#xff09;》&#xff0c;我国数据安全监管的“另一只靴子”即将落地。这份《办法》首次在国家法规层面&#xff0c;为企业开展数据安全风险评估构筑了强制性、系统化的操作框架&a…

作者头像 李华