Spring Boot :使用 Spring Cache 注解方式集成 Redis
一、项目概述本实战教程将演示如何在 Spring Boot 项目中通过 Spring Cache 注解方式集成 Redis实现高效的数据缓存功能。我们将创建一个简单的用户管理系统展示各种缓存注解的使用方法。【工程增强说明】Spring Cache 本质上是一个缓存抽象层它并不关心你底层用的是 Redis、EhCache 还是 Caffeine它只定义了• CacheManager• Cache• CacheOperation真正决定缓存行为的是你配置的 CacheManager 实现而我们这里选择的是RedisCacheManager这意味着你的缓存具备本项目适合• 中大型 Spring Boot 后端服务• 分布式系统缓存标准模板• 公司级缓存规范示例【生产定位】这不是“Hello Redis”而是可以直接拿去当公司缓存架构样板的工程模板。二、环境准备2.1 依赖配置!--pom.xml--?xml version1.0encodingUTF-8?project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersionparentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion3.1.0/versionrelativePath//parentgroupIdcom.example/groupIdartifactIdredis-cache-demo/artifactIdversion1.0.0/versionpropertiesjava.version17/java.version/propertiesdependencies!--SpringBootWeb--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency!--SpringBootDataRedis--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId/dependency!--SpringBootCache--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-cache/artifactId/dependency!--Redis连接池--dependencygroupIdorg.apache.commons/groupIdartifactIdcommons-pool2/artifactId/dependency!--Lombok--dependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependency!--单元测试--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependency!--缓存注解处理器--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-configuration-processor/artifactIdoptionaltrue/optional/dependency/dependencies/project【生产补充这几项依赖的真实职责】【版本选择说明】你用的是SpringBoot3.1.0Java17这意味着• Spring Framework 6.x• Jakarta 命名空间• 默认使用 Lettuce 客户端• Redis 7 完美适配是 当前主流生产版本组合非常优秀。2.2 Redis 配置spring:application:name:redis-cache-demo redis:host:localhost port:6379password:123456database:0timeout:2000ms lettuce:pool:max-active:8max-wait:-1ms max-idle:8min-idle:0cache:type:redis redis:time-to-live:600000cache-null-values:truekey-prefix:CACHE:use-key-prefix:true【生产级参数解读】【生产建议版】生产环境更推荐spring:cache:redis:time-to-live:1800000cache-null-values:falsekey-prefix:PROD_CACHE:三、核心代码实现这一部分是整篇文章的灵魂。Spring Cache 用得好不好80% 都取决于这里的设计是否“工程化”。3.1 缓存配置类ConfigurationEnableCachingpublicclassRedisCacheConfig{/** * 自定义Redis缓存配置 */BeanpublicRedisCacheConfigurationredisCacheConfiguration(){returnRedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(10))// 默认缓存10分钟.disableCachingNullValues()// 不缓存null值.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(newStringRedisSerializer())).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(newGenericJackson2JsonRedisSerializer()));}/** * 自定义缓存管理器配置 * 可以为不同的缓存名称设置不同的过期时间 */BeanpublicRedisCacheManagerBuilderCustomizerredisCacheManagerBuilderCustomizer(){returnbuilder-builder.withCacheConfiguration(userCache,RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(5)).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(newGenericJackson2JsonRedisSerializer()))).withCacheConfiguration(productCache,RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(30)).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(newGenericJackson2JsonRedisSerializer()))).withCacheConfiguration(shortCache,RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(30)));}}【工程级解读】这段代码做了三件非常关键的事【生产补充 1为什么必须统一序列化】如果你不显式指定.serializeValuesWith(...)Spring Boot 3 默认会使用JdkSerializationRedisSerializer问题是• Redis 里是二进制看不懂• Java 类变动就反序列化失败• 跨语言无法使用而你现在用的是GenericJackson2JsonRedisSerializer这是生产最优解之一【生产补充 2CacheName 的设计就是“缓存分区”】你现在的userCache productCache shortCache本质等价于这就是缓存层的领域模型分区设计。【高级建议TTL 加随机防雪崩】生产建议DurationbaseDuration.ofMinutes(10);longrandomThreadLocalRandom.current().nextLong(60);.entryTtl(base.plusSeconds(random))避免大量 Key 同时失效。3.2 实体类DataNoArgsConstructorAllArgsConstructorpublicclassUserimplementsSerializable{privateLongid;privateStringusername;privateStringemail;privateIntegerage;privateLocalDateTimecreateTime;privateLocalDateTimeupdateTime;}【生产补充Serializable 不是给 Redis 用的】JSON 序列化不需要 Serializable这个接口主要用于• Session• RPC• JVM 内对象传输保留它是良好习惯但不要误以为 Redis 依赖它。3.3 服务层实现缓存注解体系实战这一节是整篇最重要的一节你这里已经写得非常专业。3.3.1 Cacheable读缓存标准模型Cacheable(keyuser: #id,unless#result null)publicUsergetUserById(Longid){log.info(从数据库查询用户: {},id);simulateSlowService();returnuserDatabase.get(id);}【缓存模型解释】这是标准的CacheAsidePattern流程先查缓存缓存没有 → 查 DB放入缓存返回结果这是互联网最经典缓存模式。【生产级 Key 设计规范】你现在的 KeyCACHE:userCache::user:123完整结构是{前缀}:{CacheName}::{业务Key}这是非常优秀的企业级规范。3.3.2 CachePut更新必写缓存CachePut(keyuser: #user.id)publicUserupdateUser(Useruser){log.info(更新用户: {},user.getId());user.setUpdateTime(LocalDateTime.now());userDatabase.put(user.getId(),user);returnuser;}【生产风险提示】CachePut 在高并发下存在一个风险如果数据库写成功但 Redis 写失败会出现数据不一致。生产环境建议• 关键路径DB 成功后 → 再删缓存• 再由下一次查询回填缓存双删模式即写 DB → 删除缓存 → 读请求触发重建而不是直接 CachePut 覆盖。3.3.3 CacheEvict缓存失效治理CacheEvict(keyuser: #id)publicvoiddeleteUserById(Longid){userDatabase.remove(id);}【生产增强双删策略】删除 DB删除缓存延迟 500ms 再删一次防止并发回写旧数据。3.3.4 Caching缓存一致性编排器Caching(evict{CacheEvict(keyuser: #oldEmail),...},put{CachePut(keyuser: #user.id),...})【工程评价】你这里的写法已经是企业级缓存一致性模型示范同时维护• ID 索引缓存• 业务组合索引缓存非常高级。3.4 统一 Key 生成器避免 Key 拼接混乱在生产项目里最容易失控的就是 Key 拼接规则。一旦大家各写各的user:idUSER_iduser::idRedis 会迅速变成“垃圾场”。所以必须集中治理。Component(customKeyGenerator)publicclassCustomKeyGeneratorimplementsKeyGenerator{OverridepublicObjectgenerate(Objecttarget,Methodmethod,Object...params){StringBuildersbnewStringBuilder();sb.append(method.getName()).append(:);for(Objectparam:params){sb.append(param).append(:);}returnsb.toString();}}使用方式Cacheable(cacheNamesuserCache,keyGeneratorcustomKeyGenerator)publicUsergetUserById(Longid){...}【工程价值】3.5 Controller 层示例完整链路RestControllerRequestMapping(/users)RequiredArgsConstructorpublicclassUserController{privatefinalUserServiceuserService;GetMapping(/{id})publicUserget(PathVariableLongid){returnuserService.getUserById(id);}PutMappingpublicUserupdate(RequestBodyUseruser){returnuserService.updateUser(user);}DeleteMapping(/{id})publicvoiddelete(PathVariableLongid){userService.deleteUserById(id);}}此时完整链路为HTTP →Controller→Service→Cache→ DB这是标准 Spring Cache Redis 架构模型。3.6 监控与运维生产必备缓存不监控 迟早出事故。必须关注Redis 层面info stats info memory info keyspace关键字段keyspace_hits keyspace_misses used_memory evicted_keysSpring 层面Micrometermanagement:endpoints:web:exposure:include:health,info,metrics,prometheus GET/actuator/metrics/cache.gets GET/actuator/metrics/cache.puts GET/actuator/metrics/cache.evictions可直接对接• Prometheus• Grafana形成缓存命中率大盘。3.7 CacheUtil 工具类兜底逃生舱Spring Cache 是声明式缓存但在极端场景你仍然需要手工控制 Redis。ComponentRequiredArgsConstructorpublicclassCacheUtil{privatefinalStringRedisTemplateredisTemplate;publicvoiddelete(Stringkey){redisTemplate.delete(key);}publicvoiddeleteBatch(CollectionStringkeys){redisTemplate.delete(keys);}publicbooleanexists(Stringkey){returnBoolean.TRUE.equals(redisTemplate.hasKey(key));}}典型使用场景• 运维紧急清缓存• 批量修复脏数据• 灰度期间定向清理四、生产级缓存治理清单如果你的项目满足下面 10 条就可以说你的缓存架构已经“工程化”了。⭐ 高并发强烈建议五、缓存三大经典事故 真实生产解法缓存用不好比不用还危险。线上 90% 的 Redis 事故都逃不开这三类5.1 缓存穿透Cache Penetration场景用户请求 ID-1/999999999Redis没有 → DB 也没有 每一次都直击数据库如果被恶意刷接口Redis完全失效DB 直接崩。解决方案一不缓存 null 参数校验spring.cache.redis.cache-null-values:falseController先做参数合法性校验if(id0){thrownewIllegalArgumentException(非法参数);}解决方案二布隆过滤器高并发必备请求 →BloomFilter→ 不存在 → 直接拒绝 → 可能存在 →Redis→ DB工程级方案• Redis Redisson BloomFilter• MySQL ID 同步初始化布隆示意RBloomFilterLongbloomFilterredissonClient.getBloomFilter(user:id:bf);bloomFilter.tryInit(10000000L,0.01);5.2 缓存击穿Cache Breakdown场景某个超级热点Keyuser:110:00:00过期10:00:011万个请求同时打 DBDB 直接被冲死。解决方案一互斥锁Cacheable(...)publicUsergetUser(Longid){synchronized(this){returnloadFromDB(id);}}缺点单机有效多实例无效。解决方案二Redis 分布式锁生产标准StringlockKeylock:user:id;if(redis.setIfAbsent(lockKey,1,5,TimeUnit.SECONDS)){// 查询 DB 并回填缓存}else{// 等待 重试}解决方案三逻辑过期高端方案缓存里存{data:{...},expireTime:2026-01-22T10:00:00}即使逻辑过期• 仍然返回旧数据• 异步线程刷新缓存• 用户无感知这才是大厂方案。5.3 缓存雪崩Cache Avalanche场景1万个KeyTTL10分钟10分钟同时失效DB 死亡。标准解法TTL 随机化longttlbaseTtlRandomUtil.randomLong(0,300);例如30分钟0~5分钟随机 兜底方案多级缓存 请求 → 本地Caffeine→Redis→ DB即使 Redis 掉了本地缓存还能抗 60 秒。5.4 Redis 挂掉时你怎么办这是面试官最爱问的。标准答案SpringCacheable(...)CircuitBreaker(nameredisBreaker,fallbackMethodfallback)六、缓存更新策略你现在用的是否正确你当前方案是CachePutpublicUserupdateUser(Useruser)这是 直接覆盖缓存型。但大厂推荐更新数据库 → 删除缓存 → 让下次自然重建原因• 防止脏数据• 防止并发覆盖• 逻辑简单推荐改成TransactionalpublicUserupdateUser(Useruser){userMapper.update(user);redisTemplate.delete(userCache::user.getId());returnuser;}七、Spring Cache 真实工作原理一句话总结Spring Cache AOP CacheManager CacheOperationSource流程方法调用 ↓CacheInterceptor↓ 查Redis↓ 有 → 返回 无 → 执行方法 → 放Redis八、总结一份真正可复制的公司级缓存规范模板1. 架构层面你已经具备HTTP ↓Controller↓ServiceSpringCache注解 ↓RedisCacheManager↓Redis并且补齐了↘ 本地缓存可选Caffeine ↘ 限流/熔断 ↘ 降级兜底这已经是完整的大厂缓存链路。2. 设计层面你已经具备3. 治理层面你已经具备这点非常重要因为能写缓存的人很多能治理缓存的人极少。4. 事故层面你已经完全免疫三大经典问题你现在的缓存体系是真正“抗事故”的。

相关新闻

【开题答辩全过程】以 基于协同过滤推荐算法的小说漫画网站设计与实现为例,包含答辩的问题和答案

【开题答辩全过程】以 基于协同过滤推荐算法的小说漫画网站设计与实现为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人,语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…

2026/7/6 2:07:15 阅读更多 →
基于微信小程序的美食点餐平台设计与实现

基于微信小程序的美食点餐平台设计与实现

前言 🌞博主介绍:✌CSDN特邀作者、全栈领域优质创作者、10年IT从业经验、码云/掘金/知乎/B站/华为云/阿里云等平台优质作者、专注于Java、小程序/APP、python、大数据等技术领域和毕业项目实战,以及程序定制化开发、文档编写、答疑辅导等。✌…

2026/7/3 15:47:16 阅读更多 →
双 MOS 管实现低压差开关电路的设计参数与选型指南

双 MOS 管实现低压差开关电路的设计参数与选型指南

目录 一、双 MOS 管开关电路核心拓扑选型 1. 方案 1:N 沟道 P 沟道互补型拓扑(无需自举,控制简单) 电路拓扑结构 工作原理 核心优势与局限性 2. 方案 2:双 N 沟道 MOS 管拓扑(需自举,大电…

2026/7/5 13:35:28 阅读更多 →

最新新闻

Docker run 命令 6 大核心参数实战:-v、-w、-e、-u、--rm、-it 组合解析

Docker run 命令 6 大核心参数实战:-v、-w、-e、-u、--rm、-it 组合解析

Docker Run 命令 6 大核心参数实战指南:-v、-w、-e、-u、--rm、-it 的组合艺术当你在终端输入docker run的那一刻,一个精密的容器化引擎便开始运作。但真正让这个简单的命令变得强大的,是那些看似不起眼的参数。本文将深入探讨六个最常用却常…

2026/7/6 2:05:46 阅读更多 →
3款轻量级骨架提取模型对比:MobilePose vs Lightweight OpenPose vs MoveNet,移动端实测 20+ FPS

3款轻量级骨架提取模型对比:MobilePose vs Lightweight OpenPose vs MoveNet,移动端实测 20+ FPS

3款轻量级骨架提取模型移动端实测:性能、精度与部署全解析在移动端和边缘计算设备上实现实时人体姿态估计一直是计算机视觉领域的难点。随着AI模型轻量化技术的进步,MobilePose、Lightweight OpenPose和MoveNet等模型让20FPS的实时骨架提取成为可能。本文…

2026/7/6 2:05:46 阅读更多 →
mRemoteNG免费远程连接管理器:3天从零到精通的完整教程

mRemoteNG免费远程连接管理器:3天从零到精通的完整教程

mRemoteNG免费远程连接管理器:3天从零到精通的完整教程 【免费下载链接】mRemoteNG mRemoteNG is the next generation of mRemote, open source, tabbed, multi-protocol, remote connections manager. 项目地址: https://gitcode.com/gh_mirrors/mr/mRemoteNG …

2026/7/6 2:03:45 阅读更多 →
抖店体验分怎么提升-4点8分实操方法-抖音电商2026规则落地

抖店体验分怎么提升-4点8分实操方法-抖音电商2026规则落地

抖店体验分怎么提升?提升到4.8全套实操方法|抖音电商2026规则落地 前言 2026抖音电商体验分权重重新划定:商品体验50%、服务体验35%、物流体验15%,4.8分是店铺核心分水岭。低于4.8分,千川流量、商品卡自然流权重、平台…

2026/7/6 2:01:44 阅读更多 →
Haiwell Cloud SCADA 3 与主流 PLC 协议对比:支持 3 类设备驱动的连接实测

Haiwell Cloud SCADA 3 与主流 PLC 协议对比:支持 3 类设备驱动的连接实测

Haiwell Cloud SCADA 3 与主流 PLC 协议深度兼容性实测报告在工业自动化系统集成领域,多品牌PLC设备的互联互通一直是工程师面临的现实挑战。海为科技最新发布的Cloud SCADA 3版本以"内置多种工业设备驱动"为核心卖点,宣称能够无缝对接西门子、…

2026/7/6 1:59:44 阅读更多 →
数字通信同步技术:3种载波同步方法对比与低信噪比场景实战

数字通信同步技术:3种载波同步方法对比与低信噪比场景实战

数字通信同步技术:3种载波同步方法对比与低信噪比场景实战在数字通信系统中,载波同步是实现可靠数据传输的核心技术之一。当信号经过信道传输后,接收端需要精确恢复发送端的载波频率和相位,才能正确解调出原始信息。尤其在低信噪比…

2026/7/6 1:59:44 阅读更多 →

日新闻

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2与MySQL单元测试兼容性:5个关键SQL语句差异与规避方案1. 单元测试中的数据库兼容性挑战在Java开发领域,单元测试是保证代码质量的重要环节。当应用涉及数据库操作时,测试环境的搭建往往成为开发者的痛点。H2数据库因其轻量级、内存模式和快…

2026/7/6 0:01:17 阅读更多 →
Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘 【免费下载链接】rbtray A fork of RBTray from http://sourceforge.net/p/rbtray/code/. 项目地址: https://gitcode.com/gh_mirrors/rb/rbtray 你是否厌倦了Windows任务栏上密密麻麻的图标&…

2026/7/6 0:01:17 阅读更多 →
Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C 运行时库一键安装终极指南:告别DLL缺失烦恼 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经遇到过这样的情况:下载了…

2026/7/6 0:05:19 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

月新闻