缓存穿透与缓存雪崩
缓存穿透
缓存穿透就是大量请求的key根本不存在于缓存中,导致请求直接到了数据库上,根本没有经过缓存这一层。流程如下:
有哪些解决办法?
- 缓存无效key
如果缓存和数据库都查不到某个 key 的数据就写一个到 Redis 中去并设置过期时间,具体命令如下: SET key value EX 10086
。这种方式可以解决请求的 key 变化不频繁的情况,如果黑客恶意攻击,每次构建不同的请求 key,会导致 Redis 中缓存大量无效的 key 。
- 布隆过滤器
通过布隆过滤器我们可以非常方便的判断一个给定数据是否存在于海量数据中。具体做法是:把所有可能存在的请求的值都存放在布隆过滤器中,当用户请求过来,先判断用户发来的请求的值是否存在于布隆过滤器中。不存在的话,直接返回请求参数错误信息给客户端,存在的话才会走下面的流程。
什么是布隆过滤器?
由二进制向量(或者说是位数组)和一系列随机映射函数(哈希函数)两部分组成的数据结构,用来检查元素是否存在给定大集合中的数据结构,这种数据结构高效且性能很好,但缺点是有一定的错误识别率和删除难度。理论上添加到集合元素越多,误报的可能性越大。
布隆过滤器的原理
当一个元素加入布隆过滤器时,步骤如下:
- 使用布隆过滤器中的哈希函数对元素值进行计算,得到哈希值(有几个哈希函数得到几个哈希值)
- 根据哈希值,在位数组中把对应下标值置为1。
当我们需要判断一个元素是否存在于布隆过滤器的时候,步骤如下:
- 对给定元素再次进行相同的哈希计算
- 得到值之后判断位数组中的每个元素是否都为1,如果都为1,说明这个值在布隆过滤器中;如果存在一个值不为1,说明元素不再布隆过滤器中。
布隆过滤器说某个元素存在,小概率会误判。布隆过滤器说某个元素不在,那么这个元素一定不在。
缓存雪崩
缓存在同一时间大面积的失效,后面的请求都直接落到了数据库上,造成数据库短时间内承受大量请求。 这就好比雪崩一样,摧枯拉朽之势,数据库的压力可想而知,可能直接就被这么多请求弄宕机了。比如:系统的缓存模块出了问题比如宕机导致不可用。造成系统的所有访问都要走数据库。
还有一种缓存雪崩的场景是:**有一些被大量访问数据(热点缓存)在某一时刻大面积失效,导致对应的请求直接落到了数据库上。**举个例子 :秒杀开始 12 个小时之前,我们统一存放了一批商品到 Redis 中,设置的缓存过期时间也是 12 个小时,那么秒杀开始的时候,这些秒杀的商品的访问直接就失效了。导致的情况就是,相应的请求直接就落到了数据库上,就像雪崩一样可怕。
解决办法:
- 针对Redis服务器不可用情况:
- 采用Redis集群,避免单机出现问题整个缓存服务都没办法使用。
- 限流,避免同时处理大量的请求、
- 针对热点缓存失效的情况:
- 设置不同的失效时间比如随机设置缓存的失效时间。
- 缓存永不失效。
缓存穿透、击穿、雪崩区别
- 缓存穿透:缓存无数据,数据库也无数据
- 缓存击穿:缓存无数据,数据库有数据,key比较集中
- 缓存雪崩:缓存无数据,数据库有数据,key比较分散
缓存击穿和缓存雪崩的区别:
主要区别在于缓存击穿是查询同一条数据或热点数据查询不到,穿过了缓存。缓存雪崩是指大量数据查询不到,穿过了缓存。