🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 缓存击穿 **查询缓存中失效的 key**。大量的请求同时查询一个 key 时,此时这个 key 正好失效了,就会导致大量的请求都落到数据库。 :-: ![缓存击穿](https://img.kancloud.cn/7f/95/7f95be7ad023fd913f6f9dba6c0b3a98_509x306.png) ### 解决方案 1. 互斥锁:(基本不用次方案) 如果从redis中没有获取到数据,就让一个线程去数据库查询数据,然后构建缓存,其他的线程就等着,过一段时间后再从redis中去获取。 这个方案能解决问题,但是一个线程构建缓存的时候,另外的线程都在睡眠或者轮询。 2. 后台续命: 后台开一个定时任务,专门主动更新即将过期的数据。 设置 key 的时候同时设置过期时间为 60 分钟,后台程序在 55 分钟时,会查询数据库并重新缓存60分钟 3. 永不过期 对热点数据不设置过期时间 ## 缓存穿透 要访问的数据缓存中没有,再查询数据库,还是没有。短时间,高密度的访问此数据,给持久层数据库造成很大的压力。 :-: ![缓存击穿](https://img.kancloud.cn/29/d4/29d4806090c935800acacf31886ff561_531x324.png) ### 解决方案 1. 缓存空对象 在数据库即使查到的是空对象,也把空对象缓存起来。 如果在某个时间,缓存为空的记录,在数据库里面有值了,怎么办? 1. 设置缓存的时候,同时设置一个过期时间,这样过期之后,就会重新去数据库查询最新的数据并缓存起来 2. 如果对实时性要求非常高的话,那就写数据库的时候,同时写缓存。这样可以保障实时性 3. 如果对实时性要求不是那么高,那就写数据库的时候给消息队列发一条数据,让消息队列再通知处理缓存的逻辑去数据库取出最新的数据 > 对于恶意攻击,请求的时候key往往各不相同,且只请求一次,那你要把这些key都缓存起来的话,因为每个key都只请求一次,那还是每次都会请求数据库,怎么办?—— 布隆过滤器 2. 布隆过滤器 当布隆过滤器说某个值存在时,这个值可能不存在;当它说不存在时,那就肯定不存在。 利用布隆过滤器先进行校验,不符合则 丢弃 :-: ![布隆过滤器](https://img.kancloud.cn/18/5c/185c85448d060d2e97dc5a390e22a189_679x321.png) ## 缓存雪崩 缓存中大多数的数据在**同一时间过期**,而查询数据量巨大,这时候,又是缓存中没有,数据库中有的情况了。请求都打到数据库上,引起数据库流量激增,压力瞬间增大,直接崩溃。 ### 解决方案 1. 互斥锁 2. 错峰过期 在设置 key 过期时间的时候,加入一个随机过期时间,可以避免大量缓存同时过期 3. 缓存集群 4. 限流器+本地缓存