温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Redis缓存穿透、缓存击穿、缓存雪崩、热点Key的示例分析

发布时间:2021-12-20 10:44:50 来源:亿速云 阅读:192 作者:小新 栏目:大数据
# Redis缓存穿透、缓存击穿、缓存雪崩、热点Key的示例分析 ## 一、缓存穿透(Cache Penetration) ### 1.1 概念与场景 缓存穿透指**查询不存在的数据**,导致请求直接穿透缓存层到达数据库。常见场景: - 恶意攻击:故意请求不存在的ID(如负值、超大数值) - 业务误操作:前端传递无效参数(如已删除的商品ID) ### 1.2 示例代码 ```java // 错误示例:未做空值校验 public Product getProduct(Long id) { // 1. 先查缓存 Product product = redisTemplate.opsForValue().get("product:" + id); if (product == null) { // 2. 缓存未命中,直接查库 product = productMapper.selectById(id); // 可能返回null redisTemplate.opsForValue().set("product:" + id, product); } return product; } 

1.3 解决方案

  1. 空值缓存:对不存在的数据也缓存空对象(需设置较短TTL)
// 改进代码 if (product == null) { product = productMapper.selectById(id); if (product == null) { redisTemplate.opsForValue().set("product:" + id, "NULL", 5, TimeUnit.MINUTES); return null; } redisTemplate.opsForValue().set("product:" + id, product); } 
  1. 布隆过滤器:预加载有效Key到布隆过滤器,先校验再查询
# Python示例 from pybloom_live import ScalableBloomFilter bf = ScalableBloomFilter(initial_capacity=1000) # 预热阶段加载所有有效ID for id in valid_ids: bf.add(id) # 查询前校验 if not id in bf: return None 

二、缓存击穿(Cache Breakdown)

2.1 概念与场景

某个热点Key突然过期时,大量并发请求直接击穿到数据库。典型场景: - 秒杀商品缓存过期 - 首页热门资讯缓存失效

2.2 示例现象

  • 监控显示QPS突然飙升
  • 数据库CPU占用率陡增
  • 响应时间从毫秒级升至秒级

2.3 解决方案

  1. 互斥锁(Mutex Lock)
public Product getProductWithLock(Long id) { String lockKey = "lock:product:" + id; try { // 尝试获取分布式锁 Boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS); if (locked) { Product product = productMapper.selectById(id); redisTemplate.opsForValue().set("product:" + id, product, 1, TimeUnit.HOURS); return product; } else { Thread.sleep(100); // 短暂等待后重试 return getProductWithLock(id); } } finally { redisTemplate.delete(lockKey); } } 
  1. 逻辑过期:实际缓存永不过期,通过额外字段控制逻辑过期时间
// 缓存数据结构 { "value": "真实数据", "expire_time": 1672502400 // 逻辑过期时间戳 } 

三、缓存雪崩(Cache Avalanche)

3.1 概念与场景

大量Key同时过期或Redis集群宕机,导致请求全部涌向数据库。典型案例: - 凌晨批量任务刷新所有缓存 - Redis主从切换期间

3.2 解决方案

  1. 差异化过期时间
// 设置基础过期时间+随机偏移量 int baseExpire = 3600; int randomExpire = new Random().nextInt(300); redisTemplate.opsForValue().set(key, value, baseExpire + randomExpire, TimeUnit.SECONDS); 
  1. 多级缓存架构
请求 → CDN → 本地缓存(Caffeine) → Redis → DB 
  1. 熔断降级机制
# 伪代码示例 def get_data(key): if circuit_breaker.is_open(): return get_data_from_backup() try: data = redis.get(key) if not data: data = db.query(key) redis.setex(key, ttl, data) return data except Exception as e: circuit_breaker.record_failure() raise e 

四、热点Key(Hot Key)

4.1 识别方法

  • 监控发现某些Key的QPS异常高(如>10万/秒)
  • Redis节点出现CPU负载倾斜

4.2 解决方案

  1. 本地缓存+Redis多副本
// Guava本地缓存 LoadingCache<String, Product> localCache = CacheBuilder.newBuilder() .maximumSize(1000) .expireAfterWrite(10, TimeUnit.SECONDS) .build(new CacheLoader<String, Product>() { @Override public Product load(String key) { return getFromRedis(key); // 从Redis集群读取 } }); 
  1. Key分片
# 将hot_key拆分为hot_key_1, hot_key_2... shard_id = hash(user_id) % 4 real_key = f"hot_key_{shard_id}" redis.get(real_key) 

五、总结对比

问题类型 核心特征 典型解决方案
缓存穿透 查询不存在数据 布隆过滤器、空值缓存
缓存击穿 单热点Key失效 互斥锁、逻辑过期
缓存雪崩 大量Key同时失效 差异化TTL、多级缓存
热点Key 单Key访问量极高 本地缓存、Key分片

实际生产环境中,建议结合监控系统(如Prometheus)和动态配置中心实现策略的实时调整。 “`

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI