《程序猿入职必会(11) · 整合 Redis 实战运用》

📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗
🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数,欢迎多多交流。👍

CSDN.gif

写在前面的话

本系列博文已连载到第11篇,上一篇文章介绍了整合MyBatis-Plus,简化数据交互。
本篇文章将在此基础上,整合Redis缓存机制,进一步提升项目能力。

关联文章:
《程序猿入职必会(1) · 搭建拥有数据交互的 SpringBoot 》
《程序猿入职必会(2) · 搭建具备前端展示效果的 Vue》
《程序猿入职必会(3) · SpringBoot 各层功能完善 》
《程序猿入职必会(4) · Vue 完成 CURD 案例 》
《程序猿入职必会(5) · CURD 页面细节规范 》
《程序猿入职必会(6) · 返回结果统一封装》
《程序猿入职必会(7) · 前端请求工具封装》
《程序猿入职必会(8) · 整合 Knife4j 接口文档》
《程序猿入职必会(9) · 用代码生成器快速开发》
《程序猿入职必会(10) · 整合 Redis(基础篇)》


Redis 缓存机制

技术简介

Tips:Redis 想必大家都不陌生了,长篇大论的介绍理论意义不大,这边仅简单说明一二。

Redis 是一个开源的高性能键值存储数据库,广泛用于缓存、消息队列、实时数据分析等场景。它支持多种数据结构,如字符串、哈希、列表、集合和有序集合等,并提供丰富的操作命令。
Redis 应用场景:数据缓存、分布式锁、消息队列、排行榜等。


整合步骤

引言:基于之前的 SpringBoot3 后端项目,并且已经完成了各层的CURD操作,之前内容可以参考 《程序猿入职必会(1) · 搭建拥有数据交互的 SpringBoot 》《程序猿入职必会(3) · SpringBoot 各层功能完善 》

**Step1、引入依赖 **

<!-- 整合 Redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

这里直接引入spring-boot-starter-data-redis依赖即可,版本号SpringBoot内置维护了。
这里好在 SpringBoot2 和 SpringBoot3 关于 Redis 的依赖没有变化,少踩一些坑。

Step2、修改配置
在 application.yml 中配置 Redis 连接信息。
这里注意一下,在 SB3.0 版本之前,属性是 spring.redis,但是在 SB3.0 版本之后,变为 spring.data.redis。

spring:
  data:
    redis:
      database: 5
      host: xx.xx.xx.xx
      port: xx
      password: xx
      timeout: 60s
      lettuce:
        pool:
          # 连接池最大连接数
          max-active: 200
          # 连接池最大阻塞等待时间(使用负值表示没有限制)
          max-wait: -1ms
          # 连接池中的最大空闲连接
          max-idle: 10
          # 连接池中的最小空闲连接
          min-idle: 0

Step3、创建Redis配置类(可选)
这边主要是设置RedisTemplate的序列化规则,让缓存值可以更直观一些,这步跳过也可以。
关于 Redis 的几种序列化策略,可以参考之前的博文:《知识点扫盲 · Redis 序列化器》

@Configuration
public class RedisConfig {
    
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        GenericFastJsonRedisSerializer serializer = new GenericFastJsonRedisSerializer();
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setKeySerializer(StringRedisSerializer.UTF_8);
        redisTemplate.setValueSerializer(serializer);
        redisTemplate.setHashKeySerializer(StringRedisSerializer.UTF_8);
        redisTemplate.setHashValueSerializer(serializer);
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}

Step4、编写 RedisService(可选)
这步也是可选的,可以直接在具体逻辑里面注入 RedisTemplate,但通常会封装一下相关逻辑。
下方也是简单示例,实战中不会如此简单。

@Service
public class RedisService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 设置数据
     */
    public void setValue(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 获取数据
     */
    public Object getValue(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    /**
     * 设置带过期时间的数据
     */
    public void setValueWithExpiration(String key, Object value, long timeout, TimeUnit unit) {
        redisTemplate.opsForValue().set(key, value, timeout, unit);
    }

    /**
     * 删除数据
     */
    public void deleteValue(String key) {
        redisTemplate.delete(key);
    }
}

Step5、修改业务并测试
直接在之前根据ID获取教师详情的接口上进行整改,加上缓存逻辑。
即先从缓存获取,缓存不存在则从数据库获取,数据库获取到值再设置回缓存,然后返回。
这也是缓存利用的常规套路。

private static final String CACHE_TEA_PREV = "TEA:";

@Autowired
private RedisService redisService;

@Autowired
private ZyTeacherInfoService zyTeacherInfoService;

@GetMapping("/{id}")
public ZyTeacherInfo get(@Parameter(description = "教师ID", required = true, in = ParameterIn.PATH) @PathVariable String id) {
    String key = CACHE_TEA_PREV + id;
    ZyTeacherInfo zyTeacherInfo = (ZyTeacherInfo) redisService.getValue(key);
    if (zyTeacherInfo == null) {
        zyTeacherInfo = zyTeacherInfoService.getById(id);
        if (zyTeacherInfo != null) {
            redisService.setValue(CACHE_TEA_PREV + id, zyTeacherInfo);
        }
    }
    return zyTeacherInfo;
}

启动程序,用 Knife4j 测试一下效果,一些正常。
image.png
现在先不细究过程,可以观察一下缓存工具,确实数据进来了,搞定收工。
image.png


过程复盘

上述步骤已经实现了 Redis 整合的目的,你可以开始用 Redis 了。
Redis 最常用的是数据缓存,可以减少访问数据库的次数,降低接口耗时。
但它还有诸多场景,本篇文章篇幅有限,先不一一展开,后续再见。
那本篇文章整合一下就结束了吗?那还没有。
接下来对结合上述整合步骤,分享一些实战和拓展知识。


用法扩展

【缓存使用封装】
先看看,上述缓存的改造版本,先缓存、再数据库,这已经算常规模式了,有啥问题?

public ZyTeacherInfo get(@Parameter(description = "教师ID", required = true, in = ParameterIn.PATH) @PathVariable String id) {
    String key = CACHE_TEA_PREV + id;
    ZyTeacherInfo zyTeacherInfo = (ZyTeacherInfo) redisService.getValue(key);
    if (zyTeacherInfo == null) {
        zyTeacherInfo = zyTeacherInfoService.getById(id);
        if (zyTeacherInfo != null) {
            redisService.setValue(CACHE_TEA_PREV + id, zyTeacherInfo);
        }
    }
    return zyTeacherInfo;
}

试想一下,如果还有其他业务逻辑,那这种写法又要来一次,或者说其他业务 Service 也要获取教师信息,那这部分逻辑也还要重复编码一次。
有重复的代码出现,所以我们才需要封装。
思路分享一下:将这部分代码抽到缓存Service中,利用泛型传递设置相关业务类。
这样可以实现大大的复用,代码里优雅不少。

Tips:逻辑较简单,暂不贴实现了,后续有需要再补充。

【注解方式】
除了前面的封装公用 Service,还是注入 RedisTemplate,都算是编程式使用(也可以封装RedisUtils)。
还有一种注解式用法,那就是 Spring-Redis 的 @Cacheable 注解方式。
这就有点类似 Spring 事务的,编程式事务和声明式事务。
@Cacheable 注解是 Spring Framework 中用于缓存的一个重要注解。它可以帮助我们在方法调用时缓存结果,从而提高应用程序的性能。下面是关于如何使用 @Cacheable 注解进行增、删、改、查的示例。

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 {

    @Cacheable("users")
    public User getUserById(Long id) {
        return new User(id, "User" + id);
    }

    @CachePut(value = "users", key = "#user.id")
    public User createUser(User user) {
        // 保存用户到数据库
        return user;
    }

    @CachePut(value = "users", key = "#user.id")
    public User updateUser(User user) {
        // 更新用户到数据库
        return user;
    }

    @CacheEvict(value = "users", key = "#id")
    public void deleteUser(Long id) {
        // 从数据库中删除用户
    }
}

【注意事项】
1、缓存使用的时候,要先定义合规的Key,不能乱起八糟;
2、查询接口通常是按查缓存-查数据库-设置缓存这个模式,既然有并设置缓存,那也要考虑删除缓存的场景,通常CURD的后台管理系统,维护业务字典表的时候,增删改接口加上删除缓存的注解。
3、存 Redis 的时候要考虑一下 Key的要有效,不同业务设置不一样的。


总结陈词

此篇文章介绍了Redis 的基础整合过程,效果还不错,仅供学习参考。
Redis 值得我们学习的功能和场景还很多,这篇仅为基础篇,后续会专栏展开。
💗 后续会逐步分享企业实际开发中的实战经验,有需要交流的可以联系博主。

CSDN_END.gif

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

战神刘玉栋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值