缓存穿透和缓存击穿是两种常见的缓存失效场景,它们都会暂时使得缓存无法起到保护后端数据库的作用,从而可能导致数据库负载升高,影响服务的性能和稳定性。
缓存穿透:
缓存穿透是指查询一个在缓存和数据库中都不存在的数据时,客户端持续发送这样的请求。由于数据不存在,因此不会被缓存起来,每次请求都会直接穿透缓存到达数据库。这种情况往往容易被恶意攻击利用,通过大量请求不存在的数据来消耗数据库资源。解决方案可以包括:
- 对请求参数进行校验,避免非法或明显不存在的数据请求。
- 使用布隆过滤器预先存储所有可能存在的数据标识,用来快速判断一个请求的数据是否可能存在,不存在则提前拦截。
- 将空值或特殊标记也放入缓存,并设置较短的有效期,虽然这种做法并不适用于所有场景,但在一定程度上可以阻止持续对数据库的无效查询。
缓存击穿:
缓存击穿特指某个热点数据(即经常被访问且存在于数据库中的数据)在缓存过期的一刹那,恰好有大量的并发请求过来,由于缓存失效,所有的请求都会直接到达数据库,从而对数据库产生瞬时的大流量冲击。这是一种“单点”热点数据失效的情况。解决方法包括:
- 对热点数据采用互斥锁(mutex key)策略,即在缓存失效时,第一个请求会尝试获取分布式锁,成功后再去数据库加载数据,其他请求则等待锁释放重新尝试从缓存获取数据。
- 设置热点数据永不过期,或者使用缓存自动刷新机制,即在缓存即将过期前由后台任务主动更新缓存,确保始终有有效的缓存存在。
总结来说,缓存穿透针对的是永远不存在的数据,而缓存击穿则是针对本来应该能缓存起来但由于某种原因(如缓存过期)导致大量并发请求直击数据库的情形。