缓存雪崩、穿透、击穿解决方案
1.缓存雪崩
什么是缓存雪崩?
缓存雪崩是指大量的热点数据在 Redis 中因为设置了相同的过期时间,导致在某一时刻同时过期失效 。如果在这个时间点恰好有大量的并发请求,这些请求都会因为在缓存中找不到数据,而全部转向后端的数据库进行查询 。这会瞬间给数据库带来巨大的压力,可能导致其响应变慢甚至宕机,从而影响整个系统的可用性 。
如何解决缓存雪崩?
分散过期时间:通过给 key 的过期时间增加一个随机值,使得 key 可以在不同的时间点过期,避免集中失效 。
使用锁或队列:当缓存失效时,可以引入互斥锁或队列机制,确保对于同一个 key,只允许一个线程去数据库进行查询并回写缓存,其他线程则等待 。
定时预先更新:通过后台线程定时地对即将过期的缓存进行预先更新,避免它们在同一时间点集中失效 。
保证缓存服务高可用:确保 Redis 自身的高可用性(例如通过集群或哨兵模式),防止因为 Redis 服务本身宕机而导致所有请求都压向数据库 。
2.缓存穿透
缓存穿透是指用户(很可能为攻击者)持续请求缓存和数据库中都不存在的数据 。由于缓存中没有这些数据,请求会绕过缓存,直接访问数据库,这会导致数据库压力过大 。
解决方案如下:
封禁IP:文档认为,应对这种恶意攻击最好的办法是直接封禁发起请求的IP地址 。
使用布隆过滤器:作为一种技术解决方案,可以在访问缓存和数据库之前增加一层布隆过滤器
原理:布隆过滤器的思想是将所有可能存在的数据提前存放到一个位图中 。当一个请求过来时,会先查询布隆过滤器 6。如果过滤器判断该数据不存在,就直接返回,从而避免了对后端数据库的查询 。
特点:它能够判断数据一定不存在,但无法判断数据一定存在,因为可能会有误判 。
弊端:使用布隆过滤器需要预先将数据初始化进去,并且不能删除元素 。
3.缓存击穿
缓存击穿指的是当一个单个的 key 过期的时候,恰好有大量的并发请求来访问这个 key 。由于此时缓存已经失效,这些并发请求会全部直接访问后端的数据库,从而对数据库造成巨大压力 。
解决:
互斥锁。具体来说,当缓存失效时,只允许第一个请求获取锁并去查询数据库,然后将查询结果
回写到 Redis 缓存中 。其他线程则等待锁被释放后,直接从已重建的缓存中获取数据。
此外,为了进一步提升性能并减少对数据库的访问,还可以采用双重检查锁的机制 。