缓存穿透(Cache Penetration)
缓存穿透指客户端请求数据时,缓存中没有该数据(cache miss),随后数据库也查询不到(data miss)。此时服务器既不能从缓存命中,
也不能从数据库获取数据,导致频繁访问数据库,可能使数据库遭受巨大压力,甚至宕机,尤其是在高并发或恶意请求场景下
典型解决方案
1.缓存空值(Cache Null Value)
无论数据库是否有数据,只要查询结果为空,都将“空值”写入缓存,并设一个较短的 TTL(例如不超过 5 分钟),以降低对数据库的后续重复访问。
优点:简单易实现,直接阻断空查询攻击。
缺点:若系统频繁查询大量不同参数的空值,缓存空间容易被占满。
2.使用布隆过滤器(Bloom Filter)
布隆过滤器是一种空间效率极高的概率型数据结构,可用来判断某个 key 是否“可能存在”于数据库中:
添加数据时,将 key 通过多个哈希函数映射到位数组上置为 1;
查询时,若某个映射位置为 0,则该数据“一定不存在”;
如果为 1,则“可能存在”,此时才继续访问缓存或数据库
适用于大规模、动态更新数据库场景。虽然存在一定误判率(可能把不存在的 key 判定为存在,再访问数据库);但空间节省显著,在大型分布式系统中应用广泛
分布式环境下布隆过滤器维护问题
更新同步难点:布隆过滤器一旦在某台服务实例中新增了数据,如何让其他节点及时同步这一变化?
删除操作受限:标准布隆过滤器天生不支持删除,即使使用计数布隆过滤器(Counting Bloom Filter)也有一定的技术复杂性和成本。
- 集中管理型布隆过滤器
将布隆过滤器存储在一个集中式服务(如 Redis)中,所有服务节点都通过它来进行查询和更新。这种方式确保了单一数据源,避免同步不一致问题
优点:管理集中、容易统一更新;
缺点:集中存储可能成为性能瓶颈;需针对高并发访问做优化。
Research-backed best practices suggest this for centralized simplicity - 分片式(Partitioned)布隆过滤器
- 大规模系统中常用的一种方案是将布隆过滤器按哈希或一致性哈希进行分片,每个节点管理一部分:
查询时只访问当前 key 对应的分片;
插入时更新对应分片。
优点:能横向扩展、减少热点压力;
缺点:可能需要跨节点查询、误判率受数据分布影响
3.限流 + 熔断 + 监控 + 黑名单
在高并发或异常请求时,采用限流和熔断机制保护后端数据库。可以结合实时监控缓存的命中率,
一旦命中率骤降(意味着大量无效查询正在打穿缓存),立即报警并开启黑名单过滤,防止系统被恶意流量压垮
4.缓存预热 + 多级缓存 + 不同过期时间设计
缓存预热:提前加载热数据进入缓存,避免首次请求时都直接打数据库;
多级缓存:例如本地缓存 → Redis → 数据库,多级架构增强容错性和响应速度;
TTL 随机化:避免大量缓存同一时刻失效造成缓存雪崩,间接缓解穿透问题