🚀Spring Boot + Redis:构建高效缓存系统
@TOC
前言 🌟
在现代应用程序中,性能是至关重要的因素之一。随着用户请求的增加,数据库负载会随之增加,这时缓存就成了提升系统性能的关键解决方案。而在缓存技术中,Redis 作为一个高效的内存数据存储引擎,已经成为了最流行的选择之一。那么,如何将 Redis 集成到 Spring Boot 中,以构建一个高效的缓存系统呢?别急,今天我们就来详细探讨如何在 Spring Boot 中使用 Redis,实现轻松的数据缓存。
1. 什么是 Redis? 🤔
Redis 是一个开源的内存数据结构存储系统,常用于缓存、消息队列等场景。它支持丰富的数据类型,如字符串、哈希、列表、集合、有序集合等,可以在内存中快速读取和写入数据,这使得 Redis 成为提升系统性能的理想选择。
为什么要使用 Redis 作为缓存?
- 高效快速:Redis 基于内存操作,读写速度非常快,比传统的数据库要高效得多。
- 数据持久化:虽然 Redis 是内存数据库,但它支持数据持久化到磁盘,保证了数据不丢失。
- 丰富的数据类型:Redis 提供了多种数据结构,能够满足各种复杂数据存储需求。
- 分布式支持:Redis 支持集群模式,适合大规模分布式部署。
2. 在 Spring Boot 中集成 Redis 🔄
Spring Boot 提供了对 Redis 的原生支持,通过 spring-boot-starter-data-redis 启动器,开发者可以非常方便地将 Redis 集成到 Spring Boot 项目中。
步骤 1: 引入依赖 🛠️
首先,在 pom.xml 文件中添加 Redis 相关的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId> <!-- Jedis 是 Redis 的客户端 -->
</dependency>
这里使用 spring-boot-starter-data-redis 来简化 Redis 集成。jedis 是 Redis 官方提供的客户端,Spring Data Redis 支持的常见客户端还有 lettuce,可以根据需求选择使用。
步骤 2: 配置 Redis 连接 📝
接下来,在 application.properties 或 application.yml 中配置 Redis 连接信息:
# Redis 配置
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=yourpassword # 如果有密码
spring.redis.database=0 # 使用的数据库索引
spring.redis.timeout=2000 # 连接超时时间,单位毫秒
在默认情况下,Redis 使用 6379 端口,并且没有密码。如果你的 Redis 配置了密码或者使用了不同的端口,记得修改这些配置。
步骤 3: 创建 Redis 配置类 🔧
虽然 Spring Boot 会自动配置 Redis,但有时我们需要对 Redis 连接池等进行个性化配置。此时可以创建一个配置类,手动配置 RedisTemplate 和 StringRedisTemplate:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 设置默认的序列化方式
template.setDefaultSerializer(RedisSerializer.json());
return template;
}
@Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {
return new StringRedisTemplate(factory);
}
}
在这个配置类中,我们通过 RedisTemplate 和 StringRedisTemplate 分别为 Redis 提供了两种不同的操作模板:
RedisTemplate用于操作 Redis 的各种数据结构,如List、Set、Hash等。StringRedisTemplate仅用于处理 String 类型的数据,通常用于缓存字符串。
代码解析:
在本次的代码演示中,我将会深入剖析每句代码,详细阐述其背后的设计思想和实现逻辑。通过这样的讲解方式,我希望能够引导同学们逐步构建起对代码的深刻理解。我会先从代码的结构开始,逐步拆解每个模块的功能和作用,并指出关键的代码段,并解释它们是如何协同运行的。通过这样的讲解和实践相结合的方式,我相信每位同学都能够对代码有更深入的理解,并能够早日将其掌握,应用到自己的学习和工作中。
这段代码展示了如何使用 Spring Data Redis 配置 Redis 连接和模板。主要功能是定义了两个 Redis 模板:一个 RedisTemplate<String, Object> 用于处理通用对象类型的数据,另一个 StringRedisTemplate 用于处理 Redis 中的字符串类型数据。
1. RedisConfig 配置类
@Configuration
public class RedisConfig {
// ...
}
@Configuration注解标记这是一个配置类,Spring 会自动扫描并加载这个类中的 Bean 定义。
2. redisTemplate Bean
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 设置默认的序列化方式
template.setDefaultSerializer(RedisSerializer.json());
return template;
}
@Bean注解标记该方法会向 Spring 容器注册一个 Bean,并作为RedisTemplate的实例提供给其他组件。RedisTemplate<String, Object>:这是一个通用的 Redis 模板,用于操作 Redis 中的键值对,其中键是String类型,值是Object类型。该模板用于执行 Redis 的基本操作,如set、get、delete等。RedisConnectionFactory:该对象提供了与 Redis 的连接。通过factory参数,RedisTemplate可以连接到 Redis 服务。template.setDefaultSerializer(RedisSerializer.json()):此行代码指定RedisTemplate使用JSON格式进行序列化和反序列化。RedisSerializer.json()返回一个将对象序列化为 JSON 格式的序列化器。通过这种方式,所有存入 Redis 中的对象都会被自动转换为 JSON 字符串,而从 Redis 中获取时也会反序列化回对象。
3. stringRedisTemplate Bean
@Bean
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {
return new StringRedisTemplate(factory);
}
StringRedisTemplate是一个简化版的RedisTemplate,专门用于操作 Redis 中的字符串数据。RedisConnectionFactory是 Redis 连接的工厂类,它用于创建 Redis 的连接。StringRedisTemplate仅支持字符串类型的键和值,因此它适用于只需要操作字符串数据的场景,如简单的键值存储。
4. 配置说明
RedisTemplate和StringRedisTemplate都依赖于RedisConnectionFactory,这是 Redis 的连接工厂,负责创建与 Redis 服务的连接。Spring 会自动配置一个默认的连接工厂,可以通过@EnableAutoConfiguration来启用 Redis 连接的自动配置。- 通过配置
RedisTemplate,我们能够定制各种数据类型的序列化方式。此处我们将所有对象序列化为 JSON,这使得我们可以存储任何类型的 Java 对象,且能保证其在 Redis 中以 JSON 格式进行存储。
5. 如何使用
在 Spring 应用中,通过注入这两个模板对象,我们就可以方便地进行 Redis 操作:
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired
private StringRedisTemplate stringRedisTemplate;
public void demo() {
// 使用 StringRedisTemplate 操作字符串
stringRedisTemplate.opsForValue().set("key", "value");
String value = stringRedisTemplate.opsForValue().get("key");
// 使用 RedisTemplate 操作对象
MyObject obj = new MyObject("test", 123);
redisTemplate.opsForValue().set("myObject", obj);
MyObject retrievedObj = (MyObject) redisTemplate.opsForValue().get("myObject");
}
小结
- 该配置类提供了对
RedisTemplate和StringRedisTemplate的自定义配置。 RedisTemplate使用了JSON序列化器,这样我们可以存储任何对象并且将它们转换为 JSON 格式存储在 Redis 中。StringRedisTemplate提供了一个更简单的接口,专门用于处理 Redis 中的字符串数据。
步骤 4: 使用 Redis 操作缓存 🌈
一切配置好之后,就可以通过 RedisTemplate 在 Spring Boot 中操作 Redis 了。下面是一些常见的 Redis 操作示例。
1. 存储和获取简单数据
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
@Service
public class RedisService {
@Autowired
private StringRedisTemplate stringRedisTemplate;
// 存储数据
public void setData(String key, String value) {
stringRedisTemplate.opsForValue().set(key, value);
}
// 获取数据
public String getData(String key) {
return stringRedisTemplate.opsForValue().get(key);
}
}
在这个示例中,我们通过 StringRedisTemplate 的 opsForValue() 方法实现了最基本的存取操作:通过 set 方法存储数据,通过 get 方法获取数据。
代码解析
在本次的代码演示中,我将会深入剖析每句代码,详细阐述其背后的设计思想和实现逻辑。通过这样的讲解方式,我希望能够引导同学们逐步构建起对代码的深刻理解。我会先从代码的结构开始,逐步拆解每个模块的功能和作用,并指出关键的代码段,并解释它们是如何协同运行的。通过这样的讲解和实践相结合的方式,我相信每位同学都能够对代码有更深入的理解,并能够早日将其掌握,应用到自己的学习和工作中。
这段代码展示了如何使用 Spring Data Redis 来存储和获取 Redis 中的数据。它通过 StringRedisTemplate 来操作 Redis,并提供了简单的 setData 和 getData 方法来存储和读取数据。
1. @Service 注解
@Service
public class RedisService {
@Service注解用于标记该类是一个 Spring 服务类,它的作用类似于@Component,用于让 Spring 托管这个类的实例,并将它作为一个 Bean 注入到 Spring 容器中。
2. @Autowired 注解
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired注解表示自动注入依赖。Spring 会自动将StringRedisTemplate类型的 Bean 注入到RedisService中。StringRedisTemplate是 Spring Data Redis 提供的一个用于操作 Redis 字符串数据的模板类。
3. setData 方法
public void setData(String key, String value) {
stringRedisTemplate.opsForValue().set(key, value);
}
- 这个方法使用
StringRedisTemplate来将数据存入 Redis 中。 opsForValue()获取到操作字符串类型数据的ValueOperations,该接口提供了很多常见的 Redis 字符串操作方法,如set、get、increment等。set(key, value)方法将key和value存入 Redis。
4. getData 方法
public String getData(String key) {
return stringRedisTemplate.opsForValue().get(key);
}
- 这个方法从 Redis 中获取指定
key的值,并返回。 opsForValue().get(key)会返回对应key的字符串值,如果该key不存在,则返回null。
使用方式
在 Spring Boot 应用中,可以通过注入 RedisService 类来进行 Redis 数据的存储和读取。以下是如何使用该服务类的示例:
@Autowired
private RedisService redisService;
public void demo() {
// 存储数据到 Redis
redisService.setData("name", "Alice");
// 获取数据
String value = redisService.getData("name");
System.out.println("Retrieved value: " + value);
}
重点说明
StringRedisTemplate仅适用于操作 Redis 中的字符串类型数据。如果需要处理其他类型的数据(如对象),应该使用RedisTemplate<String, Object>。opsForValue()方法提供了对 Redis 中字符串的操作接口,常用于存储简单的键值对。
小结
RedisService是一个服务类,封装了 Redis 存取操作,提供了setData和getData方法来与 Redis 交互。- 使用了
StringRedisTemplate来进行 Redis 字符串类型数据的存储与读取。 - 该类可以方便地集成到 Spring Boot 应用中,用于处理缓存、会话存储或简单的键值存储等功能。
2. 使用 RedisTemplate 操作复杂数据结构
Redis 还支持多种数据类型,如 List、Hash 等,下面是如何通过 RedisTemplate 操作这些数据类型的示例。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@Service
public class RedisTemplateService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// 存储对象
public void setObject(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
// 获取对象
public Object getObject(String key) {
return redisTemplate.opsForValue().get(key);
}
// 存储 List
public void setList(String key, List<String> list) {
redisTemplate.opsForList().rightPushAll(key, list);
}
// 获取 List
public List<String> getList(String key) {
return redisTemplate.opsForList().range(key, 0, -1);
}
}
代码解析
在本次的代码演示中,我将会深入剖析每句代码,详细阐述其背后的设计思想和实现逻辑。通过这样的讲解方式,我希望能够引导同学们逐步构建起对代码的深刻理解。我会先从代码的结构开始,逐步拆解每个模块的功能和作用,并指出关键的代码段,并解释它们是如何协同运行的。通过这样的讲解和实践相结合的方式,我相信每位同学都能够对代码有更深入的理解,并能够早日将其掌握,应用到自己的学习和工作中。
这段代码展示了如何使用 RedisTemplate 来存储和获取 Redis 中的不同数据类型(如对象、列表等)。与之前的 StringRedisTemplate 示例不同,RedisTemplate 提供了更为通用的方式,支持存储各种类型的数据。
1. @Service 注解
@Service
public class RedisTemplateService {
@Service注解用于标记RedisTemplateService类为一个 Spring 服务类,使其能够被 Spring 容器管理。
2. @Autowired 注解
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Autowired注解表示自动注入依赖。这里RedisTemplate<String, Object>类型的 Bean 被注入到RedisTemplateService中。RedisTemplate是一个通用的 Redis 操作类,可以操作 Redis 中的各种数据类型,如字符串、列表、哈希、集合等。
3. setObject 方法
public void setObject(String key, Object value) {
redisTemplate.opsForValue().set(key, value);
}
- 该方法使用
redisTemplate.opsForValue()来存储一个对象类型的值。 opsForValue()提供了对 Redis 字符串类型的操作,尽管这里存储的是一个Object,RedisTemplate会自动进行序列化,将对象转换为字节数组存储在 Redis 中。
4. getObject 方法
public Object getObject(String key) {
return redisTemplate.opsForValue().get(key);
}
- 该方法从 Redis 获取存储在
key下的值,并将其返回。 opsForValue().get(key)返回的是存储的对象,RedisTemplate会自动进行反序列化,返回原始的对象类型。
5. setList 方法
public void setList(String key, List<String> list) {
redisTemplate.opsForList().rightPushAll(key, list);
}
- 该方法使用
redisTemplate.opsForList()来存储一个字符串列表(List<String>)。 rightPushAll(key, list)将list中的所有元素依次压入 Redis 列表的右端。
6. getList 方法
public List<String> getList(String key) {
return redisTemplate.opsForList().range(key, 0, -1);
}
- 该方法从 Redis 获取存储在
key下的列表,并返回该列表的所有元素。 opsForList().range(key, 0, -1)返回从 Redis 列表中获取的所有元素,其中0是起始索引,-1表示获取整个列表。
使用方式
在 Spring Boot 应用中,您可以通过注入 RedisTemplateService 类来进行 Redis 数据的存储和读取。以下是如何使用该服务类的示例:
@Autowired
private RedisTemplateService redisTemplateService;
public void demo() {
// 存储一个对象到 Redis
redisTemplateService.setObject("user", new User("Alice", 30));
// 获取对象
User user = (User) redisTemplateService.getObject("user");
System.out.println("Retrieved user: " + user);
// 存储一个列表到 Redis
List<String> languages = Arrays.asList("Java", "Python", "C++");
redisTemplateService.setList("languages", languages);
// 获取列表
List<String> retrievedLanguages = redisTemplateService.getList("languages");
System.out.println("Retrieved languages: " + retrievedLanguages);
}
注意事项
-
对象存储与序列化:
- 当使用
RedisTemplate存储对象时,Spring Data Redis 会自动使用默认的序列化机制(JdkSerializationRedisSerializer)将对象转化为字节数组进行存储。 - 如果希望自定义序列化方式,可以使用
GenericJackson2JsonRedisSerializer等其他序列化机制。
- 当使用
-
列表存储:
opsForList()提供了对 Redis 列表的操作支持,可以用来执行如rightPushAll、range等操作,操作的是 Redis 的列表类型。
小结
RedisTemplateService类封装了 Redis 数据存储和读取的基本操作,支持存储对象和列表。- 使用
RedisTemplate<String, Object>,可以灵活地操作 Redis 中的多种数据类型。 - 通过
opsForValue()和opsForList(),分别实现了对象和列表的存储与读取。 - 该类可以帮助你更方便地操作 Redis 中的复杂数据结构。
步骤 5: 缓存注解实现自动缓存 🧩
Spring 提供了一个非常便捷的方式来与 Redis 进行集成,那就是使用缓存注解(@Cacheable, @CachePut, @CacheEvict)。这些注解可以帮助你自动实现缓存操作,无需手动操作 RedisTemplate。
代码示例
- 启用缓存功能
在 Spring Boot 应用中,只需要在主类或者配置类上加上 @EnableCaching 注解,就可以启用缓存支持:
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableCaching
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- 使用
@Cacheable注解
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Cacheable(value = "userCache", key = "#userId")
public User getUserById(Long userId) {
// 模拟数据库操作
System.out.println("Fetching user from database...");
return new User(userId, "John Doe");
}
}
在这个示例中,@Cacheable 注解会自动将方法的返回值缓存到 Redis 中,当下次请求相同 userId 时,Spring 会直接从 Redis 中获取数据,而不是重新执行方法。
代码解析:
在本次的代码演示中,我将会深入剖析每句代码,详细阐述其背后的设计思想和实现逻辑。通过这样的讲解方式,我希望能够引导同学们逐步构建起对代码的深刻理解。我会先从代码的结构开始,逐步拆解每个模块的功能和作用,并指出关键的代码段,并解释它们是如何协同运行的。通过这样的讲解和实践相结合的方式,我相信每位同学都能够对代码有更深入的理解,并能够早日将其掌握,应用到自己的学习和工作中。
这段代码演示了如何在 Spring Boot 中使用 缓存 来提高应用程序的性能,具体使用了 @EnableCaching 和 @Cacheable 注解来启用和配置缓存。
代码解析
1. 启用缓存功能
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableCaching
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@SpringBootApplication: 这是一个组合注解,包含了@Configuration,@EnableAutoConfiguration, 和@ComponentScan。它表示这是一个 Spring Boot 应用的入口类。@EnableCaching: 这个注解用于启用 Spring 的缓存功能。它会自动配置 Spring Cache 抽象层,使得在应用中能够使用缓存相关的注解,如@Cacheable、@CachePut、@CacheEvict等。
SpringApplication.run(Application.class, args); 会启动 Spring Boot 应用并自动进行缓存配置。
2. 使用 @Cacheable 注解进行缓存
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Cacheable(value = "userCache", key = "#userId")
public User getUserById(Long userId) {
// 模拟数据库操作
System.out.println("Fetching user from database...");
return new User(userId, "John Doe");
}
}
@Service: 这是一个服务类注解,标识该类是一个服务层组件,Spring 会将它自动注册到应用上下文中。@Cacheable(value = "userCache", key = "#userId"):@Cacheable注解表示该方法的返回值会被缓存。具体来说,当方法被调用时,Spring 会检查缓存中是否已有相应的值。如果有,直接返回缓存中的值;如果没有,执行方法并将返回结果存入缓存。value:缓存的名称,这里是"userCache",表示使用名为userCache的缓存。key:缓存的 key,"#userId"表示使用方法参数userId作为缓存的 key。这样不同的userId会对应不同的缓存值。
3. 缓存操作
当你调用 getUserById 方法时,第一次调用时会从数据库(模拟的)获取数据,并将结果缓存。之后再调用相同的 userId 时,Spring 会直接从缓存中返回数据,而不再执行数据库查询操作。
流程分析
-
第一次调用
getUserById(1L)时,"Fetching user from database..."会被打印出来,说明从数据库获取了数据。同时,这个结果会被缓存,缓存的 key 是1L,缓存的 value 是User(1L, "John Doe")。 -
第二次调用
getUserById(1L)时,Spring 会检查缓存中是否存在 key 为1L的数据。如果存在,它将直接返回缓存中的值,而不再执行数据库操作,也不会打印"Fetching user from database..."。 -
如果调用
getUserById(2L),缓存中没有该 key,方法会被执行并缓存结果。每个不同的userId会有独立的缓存。
小结
- 缓存的优势:缓存的主要作用是减少数据库或其他外部资源的访问,从而提升应用的响应速度和性能。通过使用
@Cacheable注解,Spring 自动为我们处理了缓存的逻辑。 - 缓存存储:可以将缓存存储在内存中(如
ConcurrentMapCache),也可以将缓存配置为使用外部缓存系统(如 Redis, EhCache, etc.)。可以通过application.properties或application.yml文件来配置缓存的存储方式。 - 缓存过期和清理:除了
@Cacheable注解,Spring 还提供了@CacheEvict和@CachePut注解,用于手动控制缓存的过期和更新。
通过这种方式,Spring 提供的缓存注解可以大大简化缓存的使用,使得开发者能够更加专注于业务逻辑的实现。
3. 小结 🏁
Spring Boot 与 Redis 的集成非常简单,通过简单的配置和少量代码,你就可以实现一个高效的缓存系统,显著提升应用的性能。通过 Redis,我们可以有效减轻数据库负担、加速数据访问,特别是在需要频繁读取相同数据的场景中。更重要的是,Spring 提供了注解驱动的缓存方案,使得缓存的管理更加方便,极大地简化了代码。
希望这篇文章能帮助你理解如何将 Redis 集成到 Spring Boot 中,并通过它提升应用的性能。如果你还没试过 Redis,赶快动手实践一下吧,构建一个更高效、更快的应用!🎉
🧧福利赠与你🧧
无论你是计算机专业的学生,还是对编程有兴趣的小伙伴,都建议直接毫无顾忌的学习此专栏「滚雪球学SpringBoot」,bug菌郑重承诺,凡是学习此专栏的同学,均能获取到所需的知识和技能,全网最快速入门SpringBoot,就像滚雪球一样,越滚越大, 无边无际,指数级提升。
最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。
同时欢迎大家关注公众号:「猿圈奇妙屋」 ,以便学习更多同类型的技术文章,免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板、技术文章Markdown文档等海量资料。
✨️ Who am I?
我是bug菌,CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云2023年度十佳博主,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;更多精彩福利点击这里;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。
-End-
- 点赞
- 收藏
- 关注作者
评论(0)