一次springboot和redis缓存的实践

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 性能缓慢是开发人员经常面临的一个反复出现且复杂的问题。解决此类问题的最常见方法之一是通过缓存。实际上,这种机制允许在任何类型的应用程序的性能方面实现显着改进。问题是处理缓存并不是一件容易的事。幸运的是,Spring Boot 透明地提供了缓存,这要归功于 Spring Boot 缓存抽象,这是一种允许一致使用各种缓存方法而对代码影响最小的机制。让我们看看开始处理它应该知道的一切。

性能缓慢是开发人员经常面临的一个反复出现且复杂的问题。解决此类问题的最常见方法之一是通过缓存。实际上,这种机制允许在任何类型的应用程序的性能方面实现显着改进。问题是处理缓存并不是一件容易的事。幸运的是,Spring Boot 透明地提供了缓存,这要归功于 Spring Boot 缓存抽象,这是一种允许一致使用各种缓存方法而对代码影响最小的机制。让我们看看开始处理它应该知道的一切。

首先,我们将介绍缓存的概念。然后,我们将研究最常见的 Spring Boot 缓存相关注解,了解最重要的注解是什么,在哪里以及如何使用它们。接下来,是时候看看在撰写本文时 Spring Boot 支持的最流行的缓存引擎有哪些。最后,我们将通过一个示例了解 Spring Boot 缓存的实际应用。

什么是缓存

缓存是一种旨在提高任何类型应用程序性能的机制。它依赖于缓存,缓存可以看作是一种临时的快速访问软件或硬件组件,用于存储数据以减少处理与相同数据相关的未来请求所需的时间。处理缓存是很复杂的,但掌握这个概念对于任何开发人员来说几乎都是不可避免的。如果您有兴趣深入研究缓存、了解它是什么、它是如何工作的以及它最重要的类型是什么,您应该首先点击这个链接。

如何在 Spring Boot 应用程序中实现 Redis 缓存?

为了使用 Spring Boot 实现 Redis 缓存,我们需要创建一个小型应用程序,该应用程序将具有 CRUD 操作。然后我们将在检索、更新和删除操作中应用 Redis 缓存功能。

我们将使用 REST 创建一个 CRUD 应用程序。在这里,假设我们的实体类是 Invoice.java。为了创建一个完整的 REST 应用程序,我们将根据行业最佳实践拥有控制器、服务和存储库层。一旦我们完成了 Invoice REST Application 的开发,我们将进一步在某些方法上应用注解来获得 Redis Cache 的好处。这是在我们的应用程序中实现 Redis 缓存的分步方法。

需要引入的依赖
<dependency> 
 <groupId>org.springframework.boot</groupId> 
 <artifactId>spring-boot-starter-data-redis</artifactId> 
 </dependency> 
复制代码
配置文件
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/rediscachetest
spring.datasource.username=root
spring.datasource.password=****
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.cache.type=redis
spring.cache.redis.cache-null-values=true
#spring.cache.redis.time-to-live=40000
复制代码

启动类注解  @EnableCaching at starter class

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
 @SpringBootApplication
 @EnableCaching
public class RedisAsaCacheWithSpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(RedisAsaCacheWithSpringBootApplication.class, args);
}
} 
复制代码
创建 Invoice.java实体类
@Data
 @NoArgsConstructor
 @AllArgsConstructor
 @Entity
public class Invoice implements Serializable{
private static final long serialVersionUID = -4439114469417994311L;
 @Id
 @GeneratedValue
private Integer invId;
private String invName;
private Double invAmount;
} 
复制代码

创建一个接口 InvoiceRepository.java

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.dev.springboot.redis.model.Invoice;
 @Repository
public interface InvoiceRepository extends JpaRepository<Invoice, Integer> {
} 
复制代码

自定义异常类

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(HttpStatus.NOT_FOUND)
public class InvoiceNotFoundException extends RuntimeException {
private static final long serialVersionUID = 7428051251365675318L;
public InvoiceNotFoundException(String message) {
super(message);
}
} 
复制代码

一个具体的实现类,中间包含一些增删改查的方法

import com.dev.springboot.redis.model.Invoice;
import java.util.List;
public interface InvoiceService {
public Invoice saveInvoice(Invoice inv);
public Invoice updateInvoice(Invoice inv, Integer invId);
public void deleteInvoice(Integer invId);
public Invoice getOneInvoice(Integer invId);
public List<Invoice> getAllInvoices();
} 
复制代码
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import com.dev.springboot.redis.exception.InvoiceNotFoundException;
import com.dev.springboot.redis.model.Invoice;
import com.dev.springboot.redis.repo.InvoiceRepository;
 @Service
public class InvoiceServiceImpl implements InvoiceService {
 @Autowired
private InvoiceRepository invoiceRepo;
 @Override
public Invoice saveInvoice(Invoice inv) {
return invoiceRepo.save(inv);
}
 @Override
@CachePut(value="Invoice", key="#invId")
public Invoice updateInvoice(Invoice inv, Integer invId) {
Invoice invoice = invoiceRepo.findById(invId)
.orElseThrow(() -> new InvoiceNotFoundException("Invoice Not Found"));
invoice.setInvAmount(inv.getInvAmount());
invoice.setInvName(inv.getInvName());
return invoiceRepo.save(invoice);
}
 @Override
@CacheEvict(value="Invoice", key="#invId")
// @CacheEvict(value="Invoice", allEntries=true) //in case there are multiple records to delete
public void deleteInvoice(Integer invId) {
Invoice invoice = invoiceRepo.findById(invId)
.orElseThrow(() -> new InvoiceNotFoundException("Invoice Not Found"));
invoiceRepo.delete(invoice);
}
 @Override
@Cacheable(value="Invoice", key="#invId")
public Invoice getOneInvoice(Integer invId) {
Invoice invoice = invoiceRepo.findById(invId)
.orElseThrow(() -> new InvoiceNotFoundException("Invoice Not Found"));
return invoice;
}
 @Override
@Cacheable(value="Invoice")
public List<Invoice> getAllInvoices() {
return invoiceRepo.findAll();
}
} 
复制代码

添加Controller接口,进行请求测试

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.dev.springboot.redis.model.Invoice;
import com.dev.springboot.redis.service.InvoiceService;
 @RestController
@RequestMapping("/invoice")
public class InvoiceController {
 @Autowired
InvoiceService invoiceService;
@PostMapping("/saveInv")
public Invoice saveInvoice(@RequestBody Invoice inv) {
return invoiceService.saveInvoice(inv);
}
@GetMapping("/allInv")
public ResponseEntity<List<Invoice>> getAllInvoices(){
return ResponseEntity.ok(invoiceService.getAllInvoices());
}
@GetMapping("/getOne/{id}")
public Invoice getOneInvoice(@PathVariable Integer id) {
return invoiceService.getOneInvoice(id);
}
@PutMapping("/modify/{id}")
public Invoice updateInvoice(@RequestBody Invoice inv, @PathVariable Integer id) {
return invoiceService.updateInvoice(inv, id);
}
@DeleteMapping("/delete/{id}")
public String deleteInvoice(@PathVariable Integer id) {
invoiceService.deleteInvoice(id);
return "Employee with id: "+id+ " Deleted !";
}
}


作者:饱饱巴士

链接:https://juejin.cn/post/7164317075693895716

来源:稀土掘金

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
1天前
|
NoSQL Java Redis
Springboot使用Redis实现分布式锁
通过这些步骤和示例,您可以系统地了解如何在Spring Boot中使用Redis实现分布式锁,并在实际项目中应用。希望这些内容对您的学习和工作有所帮助。
108 83
|
10天前
|
缓存 NoSQL 中间件
Redis,分布式缓存演化之路
本文介绍了基于Redis的分布式缓存演化,探讨了分布式锁和缓存一致性问题及其解决方案。首先分析了本地缓存和分布式缓存的区别与优劣,接着深入讲解了分布式远程缓存带来的并发、缓存失效(穿透、雪崩、击穿)等问题及应对策略。文章还详细描述了如何使用Redis实现分布式锁,确保高并发场景下的数据一致性和系统稳定性。最后,通过双写模式和失效模式讨论了缓存一致性问题,并提出了多种解决方案,如引入Canal中间件等。希望这些内容能为读者在设计分布式缓存系统时提供有价值的参考。感谢您的阅读!
Redis,分布式缓存演化之路
|
2月前
|
存储 缓存 NoSQL
解决Redis缓存数据类型丢失问题
解决Redis缓存数据类型丢失问题
187 85
|
10天前
|
存储 缓存 NoSQL
Redis哈希结构在提升数据检索速度中的实践应用
本文详细介绍了 Redis 哈希结构的特点、常见使用场景以及如何在实际应用中利用哈希结构提升数据检索速度。通过合理使用 Redis 哈希结构,可以显著提高系统的性能和响应速度。在实际开发中,结合具体业务需求,灵活运用 Redis 提供的多种数据结构,构建高效的缓存和数据存储解决方案。希望本文能帮助您更好地理解和应用 Redis 哈希结构,提升数据检索速度。
41 18
|
17天前
|
缓存 NoSQL Java
springboot怎么使用rides缓存方法的返回值 完整例子
通过上述步骤,我们成功地在 Spring Boot 项目中集成了 Redis 缓存,并通过注解的方式实现了方法返回值的缓存。这种方式不仅提高了系统的性能,还简化了缓存管理的复杂度。使用 Spring Boot 的缓存注解和 Redis,可以轻松地实现高效、可靠的缓存机制。
53 23
|
1月前
基于springboot+thymeleaf+Redis仿知乎网站问答项目源码
基于springboot+thymeleaf+Redis仿知乎网站问答项目源码
132 36
|
29天前
|
缓存 NoSQL JavaScript
Vue.js应用结合Redis数据库:实践与优化
将Vue.js应用与Redis结合,可以实现高效的数据管理和快速响应的用户体验。通过合理的实践步骤和优化策略,可以充分发挥两者的优势,提高应用的性能和可靠性。希望本文能为您在实际开发中提供有价值的参考。
55 11
|
1月前
|
存储 缓存 NoSQL
云端问道21期方案教学-应对高并发,利用云数据库 Tair(兼容 Redis®*)缓存实现极速响应
云端问道21期方案教学-应对高并发,利用云数据库 Tair(兼容 Redis®*)缓存实现极速响应
|
1月前
|
缓存 NoSQL 关系型数据库
云端问道21期实操教学-应对高并发,利用云数据库 Tair(兼容 Redis®)缓存实现极速响应
本文介绍了如何通过云端问道21期实操教学,利用云数据库 Tair(兼容 Redis®)缓存实现高并发场景下的极速响应。主要内容分为四部分:方案概览、部署准备、一键部署和完成及清理。方案概览中,展示了如何使用 Redis 提升业务性能,降低响应时间;部署准备介绍了账号注册与充值步骤;一键部署详细讲解了创建 ECS、RDS 和 Redis 实例的过程;最后,通过对比测试验证了 Redis 缓存的有效性,并指导用户清理资源以避免额外费用。
|
2月前
|
缓存 监控 NoSQL
Redis经典问题:缓存穿透
本文详细探讨了分布式系统和缓存应用中的经典问题——缓存穿透。缓存穿透是指用户请求的数据在缓存和数据库中都不存在,导致大量请求直接落到数据库上,可能引发数据库崩溃或性能下降。文章介绍了几种有效的解决方案,包括接口层增加校验、缓存空值、使用布隆过滤器、优化数据库查询以及加强监控报警机制。通过这些方法,可以有效缓解缓存穿透对系统的影响,提升系统的稳定性和性能。