哈尔滨怎样关键词优化帮助网站网站做优化
哈尔滨怎样关键词优化,帮助网站网站做优化,如何做好电商网站平面设计,wordpress 简介主题一、项目概述
本实战教程将演示如何在 Spring Boot 项目中通过 Spring Cache 注解方式集成 Redis#xff0c;实现高效的数据缓存功能。我们将创建一个简单的用户管理系统#xff0c;展示各种缓存注解的使用方法。
【工程增强说明】
Spring Cache 本质上是一个缓存抽象层}/** * 自定义缓存管理器配置 * 可以为不同的缓存名称设置不同的过期时间 */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. 事故层面你已经完全免疫三大经典问题你现在的缓存体系是真正“抗事故”的。