一.缓存雪崩
缓存雪崩一般指的是有大量的key在同一时间失效,此时有大量的请求同时发送至数据库,导致数据库压力突然增大,数据库发生宕机。如下图所展示:
解决方案:
-
首先我们可以避免给大量数据设置同一过期时间。我们可以在用命令EXPIRE命令给每一条数据设置时间的时候,给这些数据多设置一个随机(1-3分钟)的随机时间,这样下来不同的数据有不同的过期时间,保证了数据在同一时间不会过期。
- 除了设置过期时间,还可以使用服务降级,来应对缓存雪崩。所谓的服务降级就是当发生缓存雪崩的时候采用不同处理机制,
当业务应用访问的是非核心数据(比如一些电商的一些属性)时,通过暂停从缓存中查询这些数据,而是自定义一些预定的数据,空值或者错误信息。
当业务应用访问的时核心数据(比如电商品的价格库存)时,我们允许查询缓存,如果缓存没有命中,可以查询数据库通过数据库查询数据。
这样一来,只有一部分查询核心数据会发送到数据库,减轻了数据库的压力。
除了大量数据同时过期还有一种方案会导致缓存雪崩,那就是Redis发生了宕机,没有办法处理请求,这样一下子请求全部到了数据库层,从而发生缓存雪崩。
一般来说Redis的处理请求量能达到数万级别,而数据库的处理请求能够达到数千级别。Redis时数据库的10倍多,当发生Redis宕机的时候,可以想象数10倍的请求发送至数据库,数据库肯定会导致宕机。
此时,如果Redis宕机了,我们要通过其他方案来对应缓存雪崩。解决方案如下:
1.是在业务系统中做服务熔断或请求限流机制。
服务熔断讲的是,当发生缓存雪崩时,为了防止引发连锁的数据库崩溃,甚至是整个系统崩溃,我们可以暂停对缓存的访问。通俗的来说就是通过停止缓存服务,当请求过来,我们不去处理请求,等到Redis服务恢复之后,再去处理请求,这样当大量请求发送时,可以保证数据的正常运行。
在业务运行的时间,我们可以通过服务器查看负载,缓存和数据库cpu占有率和内存利用率和访问请求的数量。当数据库所在的服务器请求量突然增加,此时就发生了缓存雪崩,我们可以启动服务熔断,暂停用户的访问,从而减低数据库的访问量。
这样下来对数据库可以起到很好的保护,对于业务来说造成了极大的影响。为了尽可能减少对业务的影响,我们可以采取限流的操作,通俗的来说限流操作,比如业务层每秒有一万的访问量,此时Redis服务发生熔断访问的数量太多,可以进行访问限流,这时候我们只让每秒一千个请求操作数据库,可以避免较大数量的请求直接去请求数据库,造成数据库宕机。
2.是在服务中搭建Redis的可靠集群,当主节点发生宕机时,此时选择一个从节点来作为新的主节点,继续提供服务,这样有效的避免了缓存发生宕机时导致缓存雪崩问题。
二.缓存击穿
-
缓存击穿指的是,针对一个请求非常频繁的请求热点数据,当没有办法在缓存中进行处理,紧接着,访问改热点数据的请求,全部请求到数据库,导致数据库压力倍增,影响其他业务的运行。缓存击穿的解决方案比较直接,对于特别频繁的数据请求,我们不要设置过期时间,这样对于热点数据的访问在Redis中进行,而Redis的高性能可以很好的处理并发访问。
三.缓存穿透
缓存穿透指的是数据不在Redis,也不再数据库中,导致请求缓存时没有数据,发生缓存确实,在去访问数据库,发现数据库中也没有数据。缓存相当于没有设置一样,应用也无法从数据库中读取消息,这样一来缓存相当于没有一样,如果有大量的数据访问,会给数据带来巨大的压力。
缓存穿透会发生在生么情况下,一般来说有两种情况:
业务层操作失误,缓存的数据和数据库的数据被误删了,因此数据库和缓存中都没有数据。
恶意攻击:专门访问数据库没有的数据。
解决方案主要有三种:
1.缓存空值或者缺省值。
一旦发生缓存穿透,我们可以针对查询的数据,在Redis中缓存一个空值或是和业务层协商确定的缺省值。紧接着,应用发送的后续请求再进行查询时,就可以直接从Redis中读取空值和缺省值,返回给业务,避免了请求都到数据库层,保持了数据库的正常运行。
2.使用布隆过滤器,快速的判断数据是否存在,避免从数据库中查询。
布隆过滤器的原理解释。布隆过滤器是有初始值为0的数据和N个哈希函数组成,可以快速地判断数据是否存在。我们想要标记某个数据可以通过三个操做完成标记。
第一使用N个哈希函数,分别计算这个数据的哈希值,得到N个哈希值。
第二把这个哈希值对应的N个哈希值对应bit数组的长度取模,的到每个哈希值所在数据中的位置。
第三我们把哈希值对应二点数组中bit为设置为1,这就完成了在布隆过滤器中的数据标记。
3.在请求入口的前端进行请求检测。缓存穿透的一个原因是有大量的恶意请求访问不存在的数据,一个有效的方案就是将锁访问的请求进行合法的检测,把恶意的请求直接过滤,不让请求到达缓存和数据库层。这样就不会出项缓存穿透。
这三大问题的应对方案总结到如下表格。
问题 | 原因 | 解决方案 |
缓存雪崩 | 大量数据同时过期 缓存服务器宕机 | 给缓存设置过期时间加随机时间,避免大量数据同一时间过期 服务降级 服务熔断,请求限流 Redis缓存主存集群 |
缓存击穿 | 访问热点数据不存在或者过期 | 不给热点数据设置过期时间,一致保留 |
缓存击穿 | 缓存和数据库中都没有的数据进行访问 | 缓存空值或缺省值 使用布隆过滤器快速判断 请求入口前端对请求合法性检查 |
尽可能的利用以下的方案:
-
针对缓存雪崩,合理的设置热点key的过期时间,要搭建缓存高可靠的集群。
-
针对缓存击穿,在缓存访问非常频繁的热点数据时,不要设置过期时间。
-
针对缓存穿透,提前在前端接口入口出对请求进行检测,规范数据库的删除操作,避免数据误删。利用布隆过滤器。