还不懂(缓存穿透/缓存击穿/缓存雪崩)?看这篇文就行了

国庆加中秋过去了 , 大家准备好学习了么?
redis 在项目中用的话 , 主要就是用作缓存了
既然用作缓存 , 那就肯定会有 缓存穿透/缓存击穿/缓存雪崩 的问题
这篇文章就来说说 , 遇到这种情况时 , 该如何去处理
缓存穿透首先咱们搞明白什么是缓存穿透?这三个词这么像 , 得把概念搞清楚不是
其实只是从字面意思上来看的话 , 大概也能知道一点儿 , 缓存穿透嘛 , 就是直接穿过了缓存 , 将请求打到了数据库上面去
一般情况下 , 去查询数据的话 , 缓存里面应该都是有的 , 但是防不住黑客呀 , 如果黑客请求查询的是数据库里面根本不存在的数据 , 数据库里面都没有的数据 , 缓存里面肯定也不会有了 , 对吧 , 那么此时请求就会打到咱们的数据库里面去 , 这就是缓存穿透
你想啊 , 黑客想要攻击的话 , 怎么可能只请求一次呢 , 肯定是大量的请求过来 , 因为是拿数据库里面不存在的 id 来请求的 , 那么这些请求毫无疑问直接打到了数据库上面去 , 那咱们的数据库可能就会因为这些大量的请求直接宕掉
如何解决呢?
咱们回到产生这个问题的场景中 , 为什么大量的请求会打到数据库上面来?因为缓存里面没有对应的 key 对吧 , 所以才会越过缓存直接到数据库
那么问题就好解决了嘛 , 缓存里面没有对应的 key ?OK, 如果这个 key 数据库里面也没有 , 那我就在 redis 里面 , 存上这个 key, 值是 null, 这样如果有查询这个 key 的请求 , 我直接返回 null 就完事儿了 , 也就不用打到数据库上面去了
注意一下 , 要记得设置它的过期时间 , 一般三到五分钟就够了
但是对方是个黑客呀 , 可能就用一个 key 去请求么?他可能会在短时间内用大量的 key 来发送请求 , 那如果一个 key 就在 redis 中存储一个 null 值的话 , 那么多 key 是不是就会存储那么多个 null 值嘞?
这样的话 ,redis 里面是不是都是值为 null 的了?
所以有没有更好的解决办法呢?
那必须得有!布隆过滤器 , 你值得尝试
什么是布隆过滤器呢?就是它能告诉你 , 某个值一定不存在或者可能存在( emmmm, 也不知道我有没有说清楚
所以可以将数据库的内容缓存一份到布隆过滤器 , 这样的话 , 当大量的请求过来的时候 ,redis 里面没有 , 没关系 , 再去布隆过滤器过滤一下 , 这样请求不用打到数据库上面去 , 就能确定这个 key 数据库中有没有
这样不就降低了数据库的压力么 , 可真是个天才~
缓存击穿缓存击穿说的是 , 在高并发情况下 , 如果好多个请求都在查询一个 key, 好巧不巧的是 , 这个 key 因为某些原因失效了(比如设置的过期时间到了 , 缓存服务器宕机了) , 这样就会导致那么多的请求都直接打到数据库上面去了
那如果这些请求的数量足够大的话 , 可能直接把数据库就干掉了
知道了造成结果的原因 , 那么寻找解决方案也就好办了
不是因为好多个请求打到了数据库嘛 , 但是它们请求的都只是一个 key, 所以这里可以使用排斥锁来实现 , 第一个请求达到请求 key 发现缓存里面没有 , 允许它去数据库查询 , 同时加锁 , 这样第二个请求 , 第三个请求…都会被锁阻塞到当前 , 不会再打到数据库 , 这样就减少了数据库的并发压力
缓存雪崩缓存雪崩 , 雪崩雪崩嘛 , 就比较严重 , 击穿说的是一个 key 失效的情况 , 雪崩指的是大规模的缓存失效情况的发生 , 这是有可能发生的 , 比如说我的缓存服务器宕机了 , 那是不是直接就大规模的缓存失效了;或者说 , 我当时为了图省事 , 好多个 key 设置的过期时间都是一样的 , 然后刚好在缓存都失效的时候 , 好多请求不同的 key 过来了
解决方案的话 , 其实就不适合使用加锁的方式去解决了 , 因为这是好多请求不同的 key, 它不是一个嘛


推荐阅读