大连中山区网站建设商场设计调研
2026/4/15 12:48:37 网站建设 项目流程
大连中山区网站建设,商场设计调研,wordpress 分享代码,施工企业上市公司有哪些Java多级缓存设计#xff1a;应对微博明星官宣的高并发场景 一、多级缓存原理与必要性 1.1 为什么需要多级缓存#xff1f; 单级缓存的问题#xff1a; 性能瓶颈#xff1a;所有请求都打到同一缓存层#xff0c;压力集中容错性差#xff1a;缓存层故障直接影响整体可…Java多级缓存设计应对微博明星官宣的高并发场景一、多级缓存原理与必要性1.1 为什么需要多级缓存单级缓存的问题性能瓶颈所有请求都打到同一缓存层压力集中容错性差缓存层故障直接影响整体可用性网络开销分布式缓存频繁网络IO热点数据压力明星官宣等热点事件导致缓存击穿1.2 多级缓存的核心思想客户端 → 本地缓存(L1) → 分布式缓存(L2) → 数据库 ↑ ↑ ↑ 最快访问 内存级 共享缓存 毫秒级响应 纳秒级访问 微秒级访问二、多级缓存设计架构2.1 典型四级缓存架构// 架构示意┌─────────────────────────────────────────┐ │ 客户端缓存(L0)│ │(App/Web端缓存HTTP缓存)│ └─────────────────────────────────────────┘ │ ┌─────────────────────────────────────────┐ │ 本地缓存(L1)│ │(Caffeine/GuavaCacheJVM进程内)│ └─────────────────────────────────────────┘ │ ┌─────────────────────────────────────────┐ │ 分布式缓存(L2)│ │(RedisCluster/RedisSentinel)│ └─────────────────────────────────────────┘ │ ┌─────────────────────────────────────────┐ │ 数据库缓存/持久层(L3)│ │(MySQLQueryCache/数据库连接池)│ └─────────────────────────────────────────┘2.2 核心设计要点publicclassMultiLevelCacheConfig{// 1. 本地缓存配置BeanpublicCacheString,ObjectlocalCache(){returnCaffeine.newBuilder().maximumSize(10_000)// 最大容量.expireAfterWrite(5,TimeUnit.SECONDS)// 短暂过期时间.expireAfterAccess(2,TimeUnit.SECONDS).recordStats()// 记录统计信息.build();}// 2. 分布式缓存配置BeanpublicRedisCacheManagerredisCacheManager(RedisConnectionFactoryfactory){RedisCacheConfigurationconfigRedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(30))// 比本地缓存长.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(newJackson2JsonRedisSerializer(Object.class)));returnRedisCacheManager.builder(factory).cacheDefaults(config).build();}}三、具体实现方案3.1 缓存加载策略ComponentpublicclassMultiLevelCacheService{AutowiredprivateCacheString,ObjectlocalCache;AutowiredprivateRedisTemplateString,ObjectredisTemplate;AutowiredprivateDataServicedataService;/** * 多级缓存读取流程 */publicObjectgetWithMultiLevel(Stringkey){// 1. 查询本地缓存 (L1)ObjectvaluelocalCache.getIfPresent(key);if(value!null){recordCacheHit(local);returnvalue;}// 2. 查询分布式缓存 (L2)valueredisTemplate.opsForValue().get(key);if(value!null){// 回填本地缓存localCache.put(key,value);recordCacheHit(redis);returnvalue;}// 3. 防止缓存击穿使用分布式锁StringlockKeylock:key;RLocklockredissonClient.getLock(lockKey);try{if(lock.tryLock(100,10,TimeUnit.MILLISECONDS)){// 双重检查valueredisTemplate.opsForValue().get(key);if(value!null){localCache.put(key,value);returnvalue;}// 4. 查询数据库 (L3)valuedataService.getFromDB(key);if(value!null){// 写入各级缓存redisTemplate.opsForValue().set(key,value,60,TimeUnit.SECONDS);localCache.put(key,value);}else{// 缓存空值防止缓存穿透cacheNullValue(key);}returnvalue;}else{// 等待其他线程加载Thread.sleep(50);returnredisTemplate.opsForValue().get(key);}}finally{lock.unlock();}}}3.2 热点数据特殊处理ComponentpublicclassHotspotCacheManager{// 热点数据本地缓存更长时间privateCacheString,ObjecthotspotCacheCaffeine.newBuilder().maximumSize(1000).expireAfterWrite(30,TimeUnit.SECONDS).build();// 热点Key探测privateConcurrentHashMapString,AtomicIntegerkeyAccessCounternewConcurrentHashMap();/** * 热点探测与特殊缓存 */publicObjectgetWithHotspotDetection(Stringkey){// 访问计数keyAccessCounter.computeIfAbsent(key,k-newAtomicInteger(0)).incrementAndGet();// 判断是否为热点例如10秒内访问超过100次if(isHotspotKey(key)){// 从热点专用缓存获取ObjectvaluehotspotCache.getIfPresent(key);if(value!null){returnvalue;}// 热点数据预加载和特殊缓存valueloadHotspotData(key);hotspotCache.put(key,value);// 延长分布式缓存时间redisTemplate.opsForValue().set(key,value,300,TimeUnit.SECONDS);returnvalue;}// 普通数据走常规流程returnmultiLevelCacheService.getWithMultiLevel(key);}privatebooleanisHotspotKey(Stringkey){AtomicIntegercounterkeyAccessCounter.get(key);returncounter!nullcounter.get()100;}}3.3 缓存一致性保证ComponentpublicclassCacheConsistencyManager{AutowiredprivateRedisPubSubredisPubSub;/** * 缓存更新时的多级同步 */TransactionalpublicvoidupdateData(Stringkey,ObjectnewValue){// 1. 更新数据库dataService.updateDB(key,newValue);// 2. 删除各级缓存先删后更新策略deleteMultiLevelCache(key);// 3. 异步更新缓存cacheUpdateExecutor.execute(()-{// 延迟双删try{Thread.sleep(500);deleteMultiLevelCache(key);}catch(InterruptedExceptione){Thread.currentThread().interrupt();}});}privatevoiddeleteMultiLevelCache(Stringkey){// 删除本地缓存localCache.invalidate(key);// 删除分布式缓存redisTemplate.delete(key);// 发布缓存失效消息其他节点监听redisPubSub.publish(cache.invalidate,key);}/** * 监听缓存失效消息 */RedisListener(topiccache.invalidate)publicvoidonCacheInvalidate(Stringkey){localCache.invalidate(key);}}四、完整的多级缓存实现示例4.1 缓存管理器Slf4jComponentpublicclassMultiLevelCacheManager{// 各级缓存配置DataConfigurationProperties(prefixcache.multi-level)publicstaticclassCacheConfig{privateLocalCacheConfiglocalnewLocalCacheConfig();privateRedisCacheConfigredisnewRedisCacheConfig();DatapublicstaticclassLocalCacheConfig{privateintmaximumSize10000;privatelongexpireAfterWrite5000;// msprivatelongexpireAfterAccess2000;// ms}DatapublicstaticclassRedisCacheConfig{privatelongdefaultExpire30000;// msprivatelonghotspotExpire300000;// msprivateStringkeyPrefixcache:;}}AutowiredprivateCacheConfigconfig;// 本地缓存实例privateLoadingCacheString,ObjectlocalCache;PostConstructpublicvoidinit(){localCacheCaffeine.newBuilder().maximumSize(config.getLocal().getMaximumSize()).expireAfterWrite(config.getLocal().getExpireAfterWrite(),TimeUnit.MILLISECONDS).expireAfterAccess(config.getLocal().getExpireAfterAccess(),TimeUnit.MILLISECONDS).recordStats().build(key-loadFromRedis(key));}/** * 核心获取方法 */publicObjectget(Stringkey){try{// 1. 尝试本地缓存returnlocalCache.get(key);}catch(Exceptione){log.warn(Local cache get failed for key: {},key,e);// 2. 降级到Redistry{ObjectvalueredisTemplate.opsForValue().get(config.getRedis().getKeyPrefix()key);if(value!null){// 异步回填本地缓存CompletableFuture.runAsync(()-localCache.put(key,value));}returnvalue;}catch(Exceptionex){log.error(Redis cache get failed for key: {},key,ex);// 3. 最后尝试数据库returndataService.getFromDB(key);}}}/** * 带降级的批量获取适用于微博Feed流 */publicMapString,ObjectbatchGet(ListStringkeys){MapString,ObjectresultnewHashMap();ListStringmissingKeysnewArrayList();// 1. 批量查询本地缓存for(Stringkey:keys){ObjectvaluelocalCache.getIfPresent(key);if(value!null){result.put(key,value);}else{missingKeys.add(key);}}// 2. 批量查询Redis使用pipeline优化if(!missingKeys.isEmpty()){ListObjectredisValuesredisTemplate.executePipelined(connection-{for(Stringkey:missingKeys){connection.stringCommands().get((config.getRedis().getKeyPrefix()key).getBytes());}returnnull;});// 处理Redis结果并回填本地缓存for(inti0;imissingKeys.size();i){StringkeymissingKeys.get(i);ObjectvalueredisValues.get(i);if(value!null){result.put(key,value);localCache.put(key,value);}}}returnresult;}}4.2 监控与降级ComponentpublicclassCacheMonitor{AutowiredprivateLoadingCacheString,ObjectlocalCache;AutowiredprivateMeterRegistrymeterRegistry;privateGaugelocalCacheSize;privateCountercacheHitCounter;privateCountercacheMissCounter;PostConstructpublicvoidinitMetrics(){// 监控本地缓存指标localCacheSizeGauge.builder(cache.local.size,localCache,cache-cache.estimatedSize()).register(meterRegistry);cacheHitCounterCounter.builder(cache.hit.total).tag(level,local).register(meterRegistry);cacheMissCounterCounter.builder(cache.miss.total).tag(level,local).register(meterRegistry);// 定时采集缓存统计ScheduledExecutorServiceexecutorExecutors.newSingleThreadScheduledExecutor();executor.scheduleAtFixedRate(this::recordStats,1,1,TimeUnit.MINUTES);}privatevoidrecordStats(){CacheStatsstatslocalCache.stats();Metrics.counter(cache.hit.rate).increment((long)(stats.hitRate()*100));Metrics.counter(cache.miss.rate).increment((long)(stats.missRate()*100));// 记录命中率到日志if(stats.hitRate()0.8){log.warn(Local cache hit rate is low: {},stats.hitRate());}}/** * 动态调整缓存策略 */Scheduled(fixedDelay60000)publicvoidadjustCachePolicy(){CacheStatsstatslocalCache.stats();// 根据命中率动态调整if(stats.hitRate()0.9){// 命中率高可以适当增加缓存时间// ...}elseif(stats.hitRate()0.6){// 命中率低可能需要调整缓存策略// ...}}}五、配置与部署建议5.1 application.yml配置# 多级缓存配置cache:multi-level:local:maximum-size:10000expire-after-write:5000expire-after-access:2000redis:default-expire:30000hotspot-expire:300000key-prefix:weibo:cache:cluster:nodes:redis1:6379,redis2:6379,redis3:6379# 热点检测配置hotspot:detection:enabled:truethreshold:100# 10秒内访问次数window-seconds:10preload:true# 是否预加载# 降级配置circuit-breaker:cache:enabled:truefailure-threshold:50timeout-ms:1005.2 部署架构建议┌─────────────────────────────────────────────────────┐ │ Load Balancer (Nginx) │ └─────────────────────────────────────────────────────┘ │ ┌───────────────┼───────────────┐ │ │ │ ┌─────┐ ┌─────┐ ┌─────┐ │App 1│ │App 2│ │App 3│ (Java应用集群) │L1 │ │L1 │ │L1 │ (本地缓存) └─────┘ └─────┘ └─────┘ │ │ │ └───────────────┼───────────────┘ │ ┌─────────────────────────────────────────────────────┐ │ Redis Cluster (L2缓存) │ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │Redis│ │Redis│ │Redis│ │Redis│ │ │ └─────┘ └─────┘ └─────┘ └─────┘ │ └─────────────────────────────────────────────────────┘ │ ┌─────────────────────────────────────────────────────┐ │ 数据库集群 (MySQL集群) │ │ 主从复制 读写分离 │ └─────────────────────────────────────────────────────┘六、针对微博场景的特殊优化6.1 明星官宣场景处理ComponentpublicclassCelebrityAnnouncementHandler{// 预加载机制EventListenerpublicvoidhandleAnnouncementEvent(CelebrityEventevent){StringcelebrityIdevent.getCelebrityId();// 1. 预热缓存preloadCelebrityData(celebrityId);// 2. 动态扩容缓存容量adjustCacheCapacity(celebrityId);// 3. 设置特殊缓存策略setSpecialCachePolicy(celebrityId);}privatevoidpreloadCelebrityData(StringcelebrityId){// 提前加载相关数据到各级缓存ListStringcacheKeysgenerateCacheKeys(celebrityId);cacheKeys.parallelStream().forEach(key-{// 从数据库加载ObjectdatadataService.getCelebrityData(key);// 写入Redis设置较长TTLredisTemplate.opsForValue().set(key,data,1,TimeUnit.HOURS);// 推送到消息队列让其他节点也预热kafkaTemplate.send(cache-preload,key);});}}七、总结关键设计原则分层设计L0→L1→L2→L3逐层降级容量规划各级缓存容量呈倒金字塔形过期策略越靠近用户过期时间越短一致性保障通过消息同步或延迟双删降级熔断任何一级缓存失败不影响整体可用性热点探测动态识别并特殊处理热点数据性能预期本地缓存命中 1msRedis缓存命中1-5ms数据库查询10-100ms整体命中率 99%这种多级缓存设计能有效应对微博明星官宣等突发高并发场景通过分级存储、热点探测、预加载等策略保证系统在高并发下的稳定性和性能。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询