SpringBoot + Redis 缓存实战

1、业务场景

本智慧社区 Redis 两处核心业务:

  1. 登录验证码:GET /captcha,存入 redis,2 分钟过期;登录校验完成删除 key;
  2. 动态路由接口/sys/user/getRouters:登录之后获取用户信息 + 路由菜单,这个接口访问频率高,数据库查询角色、菜单树,缓存到 redis,减少 mysql 查询。

用户修改角色 / 修改菜单之后,需要主动删除对应缓存 key,保证下次读取最新数据。

2、pom 依赖

复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring‑boot‑starter‑data‑redis</artifactId>
</dependency>

application.yml 配置 redis 连接,timeout,连接池。

3、RedisTemplate 配置类(重点解决序列化乱码)

默认 JDK 序列化,key 和 value 出现 \xAC\xED 乱码;改用 Jackson2JsonRedisSerializer。

复制代码
@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory){
        RedisTemplate<String,Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        //设置key序列化
        StringRedisSerializer keySerializer = new StringRedisSerializer();
        template.setKeySerializer(keySerializer);
        template.setHashKeySerializer(keySerializer);
        //value JSON序列化
        Jackson2JsonRedisSerializer<Object> jsonSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
        jsonSerializer.setObjectMapper(mapper);
        template.setValueSerializer(jsonSerializer);
        template.setHashValueSerializer(jsonSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

4、验证码业务(前面博客 captcha 接口已经用到)

复制代码
//存储验证码,key=captcha:{uuid},value验证码,2分钟过期
redisTemplate.opsForValue().set("captcha:"+uuid,code,2,TimeUnit.MINUTES);
//登录成功删除验证码
redisTemplate.delete("captcha:"+uuid);

5、动态路由菜单缓存业务 getRouters

复制代码
public Result getRouters(Long userId){
    String cacheKey = "router:user:"+userId;
    //1.先查缓存
    Object cacheObj = redisTemplate.opsForValue().get(cacheKey);
    if(cacheObj != null){
        return Result.success(cacheObj);
    }
    //2.缓存未命中,查询数据库:用户信息,角色,菜单树组装routers
    RouterVO vo = buildRouterByDb(userId);
    //3.写入缓存,设置过期时间
    redisTemplate.opsForValue().set(cacheKey,vo,1,TimeUnit.HOURS);
    return Result.success(vo);
}

缓存失效策略:当修改角色、修改菜单接口执行完成,执行删除缓存 key。

复制代码
//修改角色完成之后清除该用户路由缓存
redisTemplate.delete("router:user:"+userId);
6、缓存设计踩坑总结
  1. 序列化乱码必须自定义 RedisTemplate,不要直接使用默认;
  2. key 命名规范:业务:模块:id,例如router:user:1、captcha:uuid;
  3. 必须设置 TTL 过期,防止 redis 内存无限膨胀;
  4. 更新数据库之后主动删除缓存,不要更新缓存(旁路缓存最佳实践);
  5. 热点数据缓存,不要缓存频繁变更数据;
  6. 防止缓存穿透:数据库不存在数据,也要缓存空值,设置短 TTL。
相关推荐
三无少女指南1 小时前
从这里开始:Java 后端与 AI 工程的三条阅读路线
java·学习路线·ai工程
ZhengEnCi1 小时前
Agent 规则管理:让 Memory 做索引、让 Skill 存规则——上下文上限实测与分工方案
后端
香蕉大香蕉(06敬畏市场)1 小时前
MySQL 单点详解(07)
java·数据库·mysql·ai·博客·八股
nice_lcj5202 小时前
深入理解 Java 反射:从 Class 对象到方法调用(含性能实测 + 迷你 IOC 实战 + 面试考点)
java·开发语言·后端·面试
骑着蜗牛撵大象3272 小时前
2026 后端 AI 工程化:Spring AI 管调用、MCP 管工具、Agent 内嵌管自治
java·人工智能·后端·spring·ai·可观测性·mcp
tryxr2 小时前
JVM 垃圾回收机制
java·jvm·gc·垃圾回收
摸爬滚打的小李3 小时前
Spring XML + WAR + Tomcat 项目启动
后端
揣一尾游鱼yu3 小时前
Spring上(IOC)笔记
java·笔记·spring·ioc
荣码4 小时前
长上下文与大文档处理:200页PDF怎么喂给AI,我踩了4个坑
java·python
IT_陈寒4 小时前
SpringBoot自动配置的坑,这次终于爬出来了
前端·人工智能·后端