【Java高阶面经:缓存篇】34、高并发下缓存穿透、击穿、雪崩怎么解决

发布于:2025-05-26 ⋅ 阅读:(28) ⋅ 点赞:(0)

在这里插入图片描述

一、缓存三大核心问题:穿透、击穿、雪崩的本质区别

(一)概念对比表

问题类型 核心特征 典型场景 危害等级
缓存穿透 数据在缓存和数据库中均不存在,请求直接穿透到数据库 恶意攻击(伪造不存在的ID)、业务逻辑漏洞 ★★★★★
缓存击穿 热点数据在缓存中过期,大量并发请求同时击穿到数据库 秒杀活动开始瞬间、热点新闻发布时刻 ★★★★☆
缓存雪崩 大量缓存数据在同一时间段集中过期,导致请求洪峰冲击数据库 批量数据加载时设置相同TTL、缓存节点故障重启 ★★★☆☆

(二)核心差异图解

穿透
击穿
雪崩
请求
缓存命中?
返回缓存数据
数据库存在?
返回空值, 缓存空数据
单线程重建缓存
多级缓存兜底+限流

二、缓存穿透:拦截非法请求的防御体系

(一)空值缓存(Null Caching)

1. 核心原理
  • 对数据库查询结果为null的Key,缓存短时间的空值(如NULL_OBJECT
  • 优势:简单高效,无需额外组件
  • 风险:恶意攻击使用不同Key时浪费内存(Key空间爆炸)
2. 代码实现(Java)
public class NullCachingDemo {
   
    private static final Object NULL_OBJECT = new Object(); // 空值标记

    public Data getData(String key) {
   
        // 1. 先查缓存
        Object cacheValue = redisTemplate.opsForValue().get(key);
        if (cacheValue == NULL_OBJECT) {
   
            return null; // 缓存空值,直接返回
        }

        // 2. 缓存未命中,查数据库
        Data data = queryFromDB(key);
        if (data == null) {
   
            // 3. 缓存空值(TTL设为5分钟)
            redisTemplate.opsForValue().set(key, NULL_OBJECT, 5, TimeUnit.MINUTES);
            return null;
        }

        // 4. 缓存正常数据
        redisTemplate.opsForValue().set(key, data, 30, TimeUnit.MINUTES);
        return data;
    }

    private Data queryFromDB(String key) {
   
        // 模拟数据库查询
        return databaseRepository.findById(key).orElse(null);
    }
}
3. 优化策略
  • TTL动态调整:根据攻击频率自动调整空值缓存时间(如攻击频繁时缩短至1分钟)
  • 内存监控:定期清理过期空值,避免内存溢出

(二)布隆过滤器(Bloom Filter)

1. 核心原理
  • 基于概率的数据结构,用多个哈希函数判断Key是否存在
  • 优势:内存占用小(100万Key约占1MB),查询效率高(O(1))
  • 缺陷:存在假阳性(误判存在),但可通过参数调整降低概率
2. 技术选型
<

网站公告

今日签到

点亮在社区的每一天
去签到