当前位置: 首页 > news >正文

陕西专业网站开发多少钱微信公众号怎么开通免费

陕西专业网站开发多少钱,微信公众号怎么开通免费,用python做网页设计,网站建设的七个步骤1. 缓存穿透问题与解决方案 1.1 什么是缓存穿透 缓存穿透是指查询一个不存在的数据,由于缓存中没有这个数据,每次请求都会直接打到数据库。 如果有恶意用户不断请求不存在的数据,就会给数据库带来巨大压力。 这种情况下,缓存失去了…

1. 缓存穿透问题与解决方案

1.1 什么是缓存穿透

缓存穿透是指查询一个不存在的数据,由于缓存中没有这个数据,每次请求都会直接打到数据库。
如果有恶意用户不断请求不存在的数据,就会给数据库带来巨大压力。
这种情况下,缓存失去了保护数据库的作用。

典型场景:

  • 用户查询一个不存在的商品ID
  • 恶意攻击者故意查询大量无效数据
  • 业务逻辑错误导致的无效查询

1.2 布隆过滤器解决方案

布隆过滤器是解决缓存穿透最有效的方案之一。它可以快速判断数据是否可能存在。

@Service
public class ProductService {@Autowiredprivate BloomFilter<String> productBloomFilter;@Autowiredprivate ProductRepository productRepository;@Cacheable(cacheNames = "productCache", key = "#productId", condition = "@productService.mightExist(#productId)")public Product getProduct(String productId) {// 只有布隆过滤器认为可能存在的数据才会查询数据库return productRepository.findById(productId).orElse(null);}public boolean mightExist(String productId) {// 布隆过滤器快速判断,如果返回false则一定不存在return productBloomFilter.mightContain(productId);}@CachePut(cacheNames = "productCache", key = "#product.id")public Product saveProduct(Product product) {// 保存商品时同步更新布隆过滤器Product savedProduct = productRepository.save(product);productBloomFilter.put(product.getId());return savedProduct;}
}

1.3 空值缓存策略

对于确实不存在的数据,我们可以缓存一个空值,避免重复查询数据库。

@Service
public class UserService {private static final String NULL_VALUE = "NULL";@Cacheable(cacheNames = "userCache", key = "#userId")public User getUserById(String userId) {User user = userRepository.findById(userId).orElse(null);// 如果用户不存在,返回一个特殊标记而不是nullreturn user != null ? user : createNullUser();}private User createNullUser() {User nullUser = new User();nullUser.setId(NULL_VALUE);return nullUser;}// 在业务层判断是否为空值缓存public User getValidUser(String userId) {User user = getUserById(userId);return NULL_VALUE.equals(user.getId()) ? null : user;}
}

2. 缓存击穿问题与解决方案

2.1 缓存击穿现象分析

缓存击穿是指热点数据的缓存过期时,大量并发请求同时访问这个数据。
由于缓存中没有数据,所有请求都会打到数据库,可能导致数据库瞬间压力过大。

常见场景:

  • 热门商品详情页面
  • 明星用户信息
  • 热点新闻内容

2.2 互斥锁解决方案

使用分布式锁确保只有一个线程去重建缓存,其他线程等待。

@Service
public class HotDataService {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;@Autowiredprivate RedissonClient redissonClient;public Product getHotProduct(String productId) {String cacheKey = "hot_product:" + productId;// 先尝试从缓存获取Product product = (Product) redisTemplate.opsForValue().get(cacheKey);if (product != null) {return product;}// 缓存未命中,使用分布式锁String lockKey = "lock:product:" + productId;RLock lock = redissonClient.getLock(lockKey);try {// 尝试获取锁,最多等待10秒,锁30秒后自动释放if (lock.tryLock(10, 30, TimeUnit.SECONDS)) {// 双重检查,防止重复查询product = (Product) redisTemplate.opsForValue().get(cacheKey);if (product != null) {return product;}// 查询数据库并更新缓存product = productRepository.findById(productId).orElse(null);if (product != null) {// 设置随机过期时间,防止缓存雪崩int expireTime = 3600 + new Random().nextInt(600); // 1小时+随机10分钟redisTemplate.opsForValue().set(cacheKey, product, expireTime, TimeUnit.SECONDS);}return product;}} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {if (lock.isHeldByCurrentThread()) {lock.unlock();}}// 获取锁失败,返回空或默认值return null;}
}

2.3 逻辑过期解决方案

设置逻辑过期时间,缓存永不过期,通过后台线程异步更新。

@Component
public class LogicalExpireCache {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;@Autowiredprivate ThreadPoolExecutor cacheRebuildExecutor;public Product getProductWithLogicalExpire(String productId) {String cacheKey = "logical_product:" + productId;// 获取缓存数据(包含逻辑过期时间)CacheData<Product> cacheData = (CacheData<Product>) redisTemplate.opsForValue().get(cacheKey);if (cacheData == null) {// 缓存不存在,同步查询并设置缓存return rebuildCacheSync(productId, cacheKey);}// 检查逻辑过期时间if (cacheData.getExpireTime().isAfter(LocalDateTime.now())) {// 未过期,直接返回return cacheData.getData();}// 已过期,异步更新缓存,先返回旧数据cacheRebuildExecutor.submit(() -> rebuildCacheAsync(productId, cacheKey));return cacheData.getData();}private Product rebuildCacheSync(String productId, String cacheKey) {Product product = productRepository.findById(productId).orElse(null);if (product != null) {CacheData<Product> cacheData = new CacheData<>();cacheData.setData(product);cacheData.setExpireTime(LocalDateTime.now().plusHours(1)); // 1小时后逻辑过期redisTemplate.opsForValue().set(cacheKey, cacheData);}return product;}private void rebuildCacheAsync(String productId, String cacheKey) {try {rebuildCacheSync(productId, cacheKey);} catch (Exception e) {log.error("异步重建缓存失败: productId={}", productId, e);}}@Datapublic static class CacheData<T> {private T data;private LocalDateTime expireTime;}
}

3. 缓存雪崩问题与解决方案

3.1 缓存雪崩场景分析

缓存雪崩是指大量缓存在同一时间过期,导致大量请求直接打到数据库。
这种情况通常发生在系统重启后或者缓存集中过期时。

典型场景:

  • 系统重启后缓存全部失效
  • 定时任务统一设置的过期时间
  • Redis服务器宕机

3.2 随机过期时间策略

通过设置随机过期时间,避免缓存同时失效。

@Service
public class AntiAvalancheService {@Cacheable(cacheNames = "randomExpireCache", key = "#key")public Object getCacheWithRandomExpire(String key) {// Spring缓存注解本身不支持随机过期,需要结合Redis操作return dataRepository.findByKey(key);}@CachePut(cacheNames = "randomExpireCache", key = "#key")public Object updateCacheWithRandomExpire(String key, Object data) {// 手动设置随机过期时间String cacheKey = "randomExpireCache::" + key;int baseExpire = 3600; // 基础过期时间1小时int randomExpire = new Random().nextInt(1800); // 随机0-30分钟redisTemplate.opsForValue().set(cacheKey, data, baseExpire + randomExpire, TimeUnit.SECONDS);return data;}
}

3.3 多级缓存架构

建立多级缓存体系,即使一级缓存失效,还有二级缓存保护。

@Service
public class MultiLevelCacheService {@Autowiredprivate CacheManager l1CacheManager; // 本地缓存@Autowiredprivate RedisTemplate<String, Object> redisTemplate; // Redis缓存public Product getProductMultiLevel(String productId) {// 一级缓存:本地缓存(Caffeine)Cache l1Cache = l1CacheManager.getCache("productL1Cache");Product product = l1Cache.get(productId, Product.class);if (product != null) {return product;}// 二级缓存:Redis缓存String redisKey = "product:" + productId;product = (Product) redisTemplate.opsForValue().get(redisKey);if (product != null) {// 回写一级缓存l1Cache.put(productId, product);return product;}// 三级:数据库查询product = productRepository.findById(productId).orElse(null);if (product != null) {// 同时更新两级缓存l1Cache.put(productId, product);redisTemplate.opsForValue().set(redisKey, product, Duration.ofHours(2)); // Redis缓存2小时}return product;}@CacheEvict(cacheNames = "productL1Cache", key = "#productId")public void evictProduct(String productId) {// 同时清除Redis缓存redisTemplate.delete("product:" + productId);}
}

4. 电商系统实战案例

4.1 商品详情页缓存策略

电商系统的商品详情页是典型的高并发场景,需要综合应用多种缓存策略。

@Service
public class ProductDetailService {@Autowiredprivate BloomFilter<String> productBloomFilter;@Autowiredprivate RedissonClient redissonClient;// 防穿透 + 防击穿的商品详情查询public ProductDetail getProductDetail(String productId) {// 1. 布隆过滤器防穿透if (!productBloomFilter.mightContain(productId)) {return null; // 商品不存在}String cacheKey = "product_detail:" + productId;// 2. 尝试从缓存获取ProductDetail detail = (ProductDetail) redisTemplate.opsForValue().get(cacheKey);if (detail != null) {return detail;}// 3. 缓存未命中,使用分布式锁防击穿String lockKey = "lock:product_detail:" + productId;RLock lock = redissonClient.getLock(lockKey);try {if (lock.tryLock(5, 30, TimeUnit.SECONDS)) {// 双重检查detail = (ProductDetail) redisTemplate.opsForValue().get(cacheKey);if (detail != null) {return detail;}// 查询数据库detail = buildProductDetail(productId);if (detail != null) {// 4. 设置随机过期时间防雪崩int expireTime = 7200 + new Random().nextInt(3600); // 2-3小时redisTemplate.opsForValue().set(cacheKey, detail, expireTime, TimeUnit.SECONDS);}return detail;}} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {if (lock.isHeldByCurrentThread()) {lock.unlock();}}return null;}private ProductDetail buildProductDetail(String productId) {// 组装商品详情信息Product product = productRepository.findById(productId).orElse(null);if (product == null) {return null;}ProductDetail detail = new ProductDetail();detail.setProduct(product);detail.setInventory(inventoryService.getInventory(productId));detail.setReviews(reviewService.getTopReviews(productId));detail.setRecommendations(recommendationService.getRecommendations(productId));return detail;}
}

4.2 用户会话缓存管理

用户会话信息需要考虑安全性和性能,采用分层缓存策略。

@Service
public class UserSessionService {// 敏感信息使用短期缓存@Cacheable(cacheNames = "userSessionCache", key = "#sessionId", condition = "#sessionId != null")public UserSession getUserSession(String sessionId) {return sessionRepository.findBySessionId(sessionId);}// 用户基础信息使用长期缓存@Cacheable(cacheNames = "userBasicCache", key = "#userId")public UserBasicInfo getUserBasicInfo(String userId) {return userRepository.findBasicInfoById(userId);}@CacheEvict(cacheNames = {"userSessionCache", "userBasicCache"}, key = "#userId")public void invalidateUserCache(String userId) {// 用户登出或信息变更时清除相关缓存log.info("清除用户缓存: {}", userId);}// 防止会话固定攻击的缓存更新@CachePut(cacheNames = "userSessionCache", key = "#newSessionId")@CacheEvict(cacheNames = "userSessionCache", key = "#oldSessionId")public UserSession refreshSession(String oldSessionId, String newSessionId, String userId) {// 生成新的会话信息UserSession newSession = new UserSession();newSession.setSessionId(newSessionId);newSession.setUserId(userId);newSession.setCreateTime(LocalDateTime.now());sessionRepository.save(newSession);sessionRepository.deleteBySessionId(oldSessionId);return newSession;}
}

5. 缓存监控与告警

5.1 缓存命中率监控

监控缓存的命中率,及时发现缓存问题。

@Component
public class CacheMetricsCollector {private final MeterRegistry meterRegistry;private final Counter cacheHitCounter;private final Counter cacheMissCounter;public CacheMetricsCollector(MeterRegistry meterRegistry) {this.meterRegistry = meterRegistry;this.cacheHitCounter = Counter.builder("cache.hit").description("Cache hit count").register(meterRegistry);this.cacheMissCounter = Counter.builder("cache.miss").description("Cache miss count").register(meterRegistry);}@EventListenerpublic void handleCacheHitEvent(CacheHitEvent event) {cacheHitCounter.increment(Tags.of("cache.name", event.getCacheName()));}@EventListenerpublic void handleCacheMissEvent(CacheMissEvent event) {cacheMissCounter.increment(Tags.of("cache.name", event.getCacheName()));}// 计算缓存命中率public double getCacheHitRate(String cacheName) {double hits = cacheHitCounter.count();double misses = cacheMissCounter.count();return hits / (hits + misses);}
}

5.2 缓存异常告警

当缓存出现异常时,及时告警并降级处理。

@Component
public class CacheExceptionHandler {@EventListenerpublic void handleCacheException(CacheErrorEvent event) {log.error("缓存异常: cache={}, key={}, exception={}", event.getCacheName(), event.getKey(), event.getException().getMessage());// 发送告警alertService.sendAlert("缓存异常", String.format("缓存 %s 发生异常: %s", event.getCacheName(), event.getException().getMessage()));// 记录异常指标meterRegistry.counter("cache.error", "cache.name", event.getCacheName()).increment();}// 缓存降级处理@Recoverpublic Object recoverFromCacheException(Exception ex, String key) {log.warn("缓存操作失败,执行降级逻辑: key={}", key);// 直接查询数据库或返回默认值return fallbackDataService.getFallbackData(key);}
}

6. 最佳实践总结

6.1 缓存策略选择指南

缓存穿透解决方案选择:

  • 数据量大且查询模式固定:使用布隆过滤器
  • 数据量小且查询随机性强:使用空值缓存
  • 对一致性要求高:布隆过滤器 + 空值缓存组合

缓存击穿解决方案选择:

  • 对实时性要求高:使用互斥锁方案
  • 对可用性要求高:使用逻辑过期方案
  • 并发量特别大:逻辑过期 + 异步更新

缓存雪崩解决方案选择:

  • 单机应用:随机过期时间 + 本地缓存
  • 分布式应用:多级缓存 + 熔断降级
  • 高可用要求:Redis集群 + 多级缓存

6.2 性能优化建议

  1. 合理设置过期时间:根据数据更新频率设置,避免过长或过短
  2. 控制缓存大小:定期清理无用缓存,避免内存溢出
  3. 监控缓存指标:关注命中率、响应时间、错误率等关键指标
  4. 预热关键缓存:系统启动时预加载热点数据
  5. 异步更新策略:对于非关键数据,采用异步更新减少响应时间

通过合理应用这些缓存策略,可以有效提升系统性能,保障服务稳定性。
记住,缓存是把双刃剑,既要享受性能提升,也要处理好数据一致性问题。

http://www.dtcms.com/a/447357.html

相关文章:

  • 张家港做网站的公司展厅设计培训
  • 网站标题怎么做响应式中文网站模板
  • 巴中建设厅网站电话美篇app怎么制作
  • 衡水网站设计公司哪家专业html简单广告代码
  • 网站开发女生工资手机wap网页
  • 广州建设集团网站黑龙江企业网站设计团队
  • 帝国cms网站地图xmlphotoshopcc
  • 网站建设策划怎么谈深圳广告公司画册设计
  • 做ppt的兼职网站有哪些海外分销平台
  • 微商城网站开发视频小程序注册方法
  • 上海市网站建设公司优秀的h5案例
  • 网站开发实例及研究网站同步到新浪微博
  • 网站建设价格山东济南兴田德润什么活动新增病例最新消息
  • 建设网站都需要哪些资料喀什网站建设百度推广
  • 河东苏州网站建设正能量网站不用下载直接进入
  • wordpress插件途径用仿网站做优化有效果吗
  • 怎么建造个人网站公众号版面设计创意
  • 企业网站备案教程中国外贸论坛
  • 外国网站的浏览器下载适合美工的网站
  • 物联网对企业网站建设的要求品质商城网站建设
  • 做网站什么空间比较好全国私人订制平台
  • 网站建设 媒体广告东莞知名企业排名
  • B树、B+树、B*树深度探索与解析:为什么数据库青睐于它们?
  • 做电子商务网站需要什么手续四川营销型网站建设公司
  • wordpress拉哈尔滨企业网站seo
  • 做网站 毕业设计wordpress重装密码
  • 公司网站设计的公司网站的建设多少钱
  • 【AI4S】基于分子图像与分子描述符的药物筛选预测模型
  • 绍兴网站建设 微德福wordpress优惠券模板
  • 韶关做网站需要多少钱网站 app开发 财务做帐