购物网站有哪些模块,秦皇岛网站seo,php 爬取网站所有链接,网站建设专业工资一、为何需要两级缓存架构#xff1f;
在分布式系统中#xff0c;Redis作为分布式缓存已广泛应用。但当系统面临超高并发读取#xff08;如热点商品详情页访问#xff09;或超低延迟要求#xff08;如金融行情数据推送#xff09;时#xff0c;纯远程缓存面临两大瓶颈
在分布式系统中Redis作为分布式缓存已广泛应用。但当系统面临超高并发读取如热点商品详情页访问或超低延迟要求如金融行情数据推送时纯远程缓存面临两大瓶颈
网络IO开销每次Redis访问需10-50ms的网络延迟带宽瓶颈单节点Redis吞吐量上限约10万QPS
通过引入Caffeine本地缓存作为一级缓存Redis作为二级缓存可实现 #mermaid-svg-mFP5xaKAPFlnOqAn {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-mFP5xaKAPFlnOqAn .error-icon{fill:#552222;}#mermaid-svg-mFP5xaKAPFlnOqAn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-mFP5xaKAPFlnOqAn .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-mFP5xaKAPFlnOqAn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-mFP5xaKAPFlnOqAn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-mFP5xaKAPFlnOqAn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-mFP5xaKAPFlnOqAn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-mFP5xaKAPFlnOqAn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-mFP5xaKAPFlnOqAn .marker.cross{stroke:#333333;}#mermaid-svg-mFP5xaKAPFlnOqAn svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-mFP5xaKAPFlnOqAn .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-mFP5xaKAPFlnOqAn .cluster-label text{fill:#333;}#mermaid-svg-mFP5xaKAPFlnOqAn .cluster-label span{color:#333;}#mermaid-svg-mFP5xaKAPFlnOqAn .label text,#mermaid-svg-mFP5xaKAPFlnOqAn span{fill:#333;color:#333;}#mermaid-svg-mFP5xaKAPFlnOqAn .node rect,#mermaid-svg-mFP5xaKAPFlnOqAn .node circle,#mermaid-svg-mFP5xaKAPFlnOqAn .node ellipse,#mermaid-svg-mFP5xaKAPFlnOqAn .node polygon,#mermaid-svg-mFP5xaKAPFlnOqAn .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-mFP5xaKAPFlnOqAn .node .label{text-align:center;}#mermaid-svg-mFP5xaKAPFlnOqAn .node.clickable{cursor:pointer;}#mermaid-svg-mFP5xaKAPFlnOqAn .arrowheadPath{fill:#333333;}#mermaid-svg-mFP5xaKAPFlnOqAn .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-mFP5xaKAPFlnOqAn .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-mFP5xaKAPFlnOqAn .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-mFP5xaKAPFlnOqAn .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-mFP5xaKAPFlnOqAn .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-mFP5xaKAPFlnOqAn .cluster text{fill:#333;}#mermaid-svg-mFP5xaKAPFlnOqAn .cluster span{color:#333;}#mermaid-svg-mFP5xaKAPFlnOqAn div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-mFP5xaKAPFlnOqAn :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 命中 未命中 命中 未命中 客户端请求 Caffeine本地缓存 Redis集群 数据库 二、核心架构设计与挑战
1. 数据访问流程
public User getUserById(Long userId) {String key user: userId;// 1. 先查CaffeineUser user caffeineCache.get(key, k - {// 2. 未命中则查RedisObject obj redisTemplate.opsForValue().get(k);if (obj ! null) return obj;// 3. Redis未命中查DBUser dbUser userMapper.selectById(userId);redisTemplate.opsForValue().set(k, dbUser, 30, TimeUnit.SECONDS);return dbUser;});return user;
}命中率提升效果本地缓存可达95%整体命中率99% 2. 关键优势对比
指标纯Redis缓存两级缓存架构提升幅度平均响应时间1-10ms100ns-1ms10-100倍数据库请求量100%1%99%Redis带宽占用100%10%-30%70%-90%
3. 核心挑战与解决方案
挑战一缓存一致性
问题场景集群中节点A更新数据节点B仍读旧缓存解决方案Redis Pub/Sub 本地缓存失效
// 配置Redis消息监听
Bean
public RedisMessageListenerContainer container(RedisConnectionFactory factory) {RedisMessageListenerContainer container new RedisMessageListenerContainer();container.setConnectionFactory(factory);container.addMessageListener((message, pattern) - {String key new String(message.getBody());caffeineCache.invalidate(key); // 失效本地缓存}, new ChannelTopic(cacheEvict));return container;
}// 数据更新时发布消息
public void updateUser(User user) {userMapper.updateById(user);redisTemplate.delete(key);redisTemplate.convertAndSend(cacheEvict, key); // 发布失效通知
}实测效果万级QPS下缓存同步延迟5ms 挑战二缓存穿透/雪崩
解决方案组合Caffeine.newBuilder().maximumSize(10_000) // 限制本地缓存数量.expireAfterWrite(10, TimeUnit.SECONDS) // 短TTL.refreshAfterWrite(1, TimeUnit.SECONDS) // 异步刷新.recordStats() // 开启监控配合Redisspring:redis:timeout: 100ms # 快速失败lettuce:pool:max-active: 200 # 连接池优化三、三种实现方案深度对比
方案1手动编码模式
适用场景需要精细控制缓存逻辑
// 手动查询两级缓存
public User queryUser(long userId) {String key user- userId;return (User) caffeineCache.get(key, k - {Object redisVal redisTemplate.opsForValue().get(k);if (redisVal ! null) return redisVal;return userMapper.selectById(userId);});
}优点完全掌控缓存逻辑 缺点代码侵入性强
方案2Spring Cache注解
配置示例
Configuration
EnableCaching
public class CacheConfig {Beanpublic CacheManager cacheManager() {CaffeineCacheManager manager new CaffeineCacheManager();manager.setCaffeine(Caffeine.newBuilder().expireAfterWrite(10, TimeUnit.SECONDS).maximumSize(1000));return manager;}
}// 业务层使用
Service
public class UserService {Cacheable(valueusers, key#userId, condition#userId%20)public User getUser(Long userId) {return userMapper.selectById(userId);}
}注解对比
注解作用关键参数Cacheable查询数据时缓存结果key, condition, unlessCachePut强制更新缓存keyCacheEvict删除缓存allEntries, beforeInvocation
方案3自定义注解推荐生产环境使用
定义注解
Target(ElementType.METHOD)
Retention(RetentionPolicy.RUNTIME)
public interface DoubleCache {String cacheName();String key(); // 支持SpEL表达式long l2TimeOut() default 120;CacheType type() default CacheType.FULL; // FULL/PUT/DELETE
}切面核心逻辑
Aspect
Component
public class CacheAspect {Around(annotation(doubleCache))public Object handleCache(ProceedingJoinPoint pjp, DoubleCache doubleCache) throws Throwable {String realKey parseKey(doubleCache, pjp); // 解析SpELswitch (doubleCache.type()) {case PUT: Object result pjp.proceed();updateCache(realKey, result); return result;case DELETE:deleteCache(realKey);return pjp.proceed();default: // FULLif (caffeineCache.getIfPresent(realKey) ! null) return caffeineCache.getIfPresent(realKey);if (redisTemplate.hasKey(realKey)) {Object val redisTemplate.opsForValue().get(realKey);caffeineCache.put(realKey, val);return val;}Object dbResult pjp.proceed();updateCache(realKey, dbResult);return dbResult;}}
}四、高可用设计最佳实践 本地缓存策略优化 Caffeine.newBuilder().maximumSize(10_000) // 防OOM.expireAfterWrite(15, TimeUnit.SECONDS) // 短TTL保新鲜.refreshAfterWrite(1, TimeUnit.SECONDS) // 后台刷新.recordStats() // 监控命中率.writer(new CacheWriter() { // 淘汰监听public void delete(String key, Object value, RemovalCause cause) {log.info(Evicted key: {}, Cause: {}, key, cause);}});Redis层优化建议 使用HashTag保证热点数据分片均衡user:{12345}:profile设置差异化TTL防雪崩baseTTL random(0, 300)大Value压缩redisTemplate.setValueSerializer(new SnappyRedisSerializer()) 监控指标体系 监控项健康阈值工具Caffeine命中率85%cache.stats().hitRate()Redis延迟50msRedis SLOWLOG本地缓存内存占用JVM堆的30%JMX Metrics
五、性能压测对比
在4节点集群测试环境16Core/32GB
场景纯Redis QPS两级缓存 QPS平均延迟商品详情读取12,00058,0008ms → 0.3ms用户信息查询8,50045,00015ms → 0.5ms库存扣减3,2003,50025ms → 22ms 结论读密集型场景性能提升5X写操作提升有限 选型建议
中小项目Spring Cache注解快速实现高并发系统自定义注解Pub/Sub同步精细控制实时性要求极高Caffeine W-TinyLFU算法98%命中率
通过两级缓存架构某电商平台在2025年大促期间成功支撑1.2亿QPSRedis成本降低60%。正确实施该架构可让您的系统在性能和成本间获得最佳平衡