关于【缓存穿透,缓存击穿,缓存雪崩,热点数据丢失】问题的解决方案

本篇文章转载自:石衫的架构笔记 微信公众号redis

前言

当咱们系统中使用到了缓存时,无论是一级缓存仍是多级缓存,它的做用就是业务系统在请求数据时,若是缓存中有,就从缓存中获取;若是缓存中没有,再去访问DB,从而减小DB的压力,缩短获取数据的时间。那么在使用缓存的过程当中,会出现哪些常见问题?咱们又如何来解决?数据库

1 缓存穿透

1.1 什么是缓存穿透

正常状况下,咱们去查询数据都是存在的。缓存

那么请求查询一条压根在数据库中就不存在的数据,即在缓存和数据库中都没有这条数据,可是请求每次在缓存中找不到,就去访问数据库,比较占用和消耗数据库的资源,这种现象,就叫作缓存穿透。服务器

1.2 穿透带来的问题

黑客攻击系统,经过缓存穿透,使用一个不存在的id,大量访问系统的接口,系统由于缓存中没有数据,而去大量的访问数据库,致使数据库资源被无效占用,影响甚至拖垮正常业务。微信

1.3 解决办法

1.3.1 缓存空值

咱们知道,缓存服务器(redis)通常是经过key value来存储缓存数据的。当有请求过来,会经过key在缓存中查找数据。而发生缓存击穿的问题,是由于缓存服务器中没有存储这些无效数据的key,从而致使无效请求访问到数据库。架构

那么咱们能够在这些请求访问数据库后,没有获得查询结果时,在缓存服务器中存储这个key,并设置它的值为null,这样当再次发生查询这个key的请求时,缓存服务器就直接返回null,不去访问数据库了。并发

可是不要忘记,设置缓存失效时间,方便正确数据的录入和更新。分布式

1.3.2 BloomFilter

BloomFilter相似于一个hbase set用来判断某个元素(key)是否存在于某个集合中。高并发

这种方式在大数据应用场景比较多,好比Hbase(HBase是一个分布式的、面向列的开源数据库)中使用它去判断数据是否在磁盘上。还有在爬虫场景判断url是否已经被爬取过。性能

这种方式能够加在第一种方案中,在缓存以前再加一层BloomFilter去查询key是否存在,若是不存在直接返回,存在再去查询缓存或者DB。

1.4 如何选择

针对大量恶意请求攻击,若是key重复多,使用第一种方案是有效的。

若是恶意请求key不重复的多,则使用第二种方案最有效。

2 缓存击穿

2.1 什么是缓存击穿

在日常高并发的系统中,大量的请求同事查询到一个key时,此时这个key正好失效了,就会致使大量的请求都转到数据库上面了,这种现象咱们成为缓存击穿。

2.2 会带来什么问题

会形成数据库访问量忽然增大,压力剧增。

2.3 如何解决

上面的现象是多个线程同时去查询数据库的这条数据,那么我能够在第一个查询数据的请求上使用一个 互斥锁 来锁住它。

其余的线程走到这一步拿不到锁就等待,等到第一个线程查询到了数据,而后作缓存,后面的线程进来发现已经有缓存了,就能够直接获取缓存,而不访问数据库了。

3 缓存雪崩

3.1 什么是缓存雪崩

在当某一时刻发生大规模的缓存失效的状况,好比你的缓存服务宕机了,会有大量的请求直接请求数据库上,结果数据库就撑不住了,也跟着挂掉了。

3.2 解决办法

3.2.1 事前:

使用集群缓存,保证缓存服务器的高可用。

好比使用redis,就要考虑到 主 从 + 哨兵和 集群 来避免redis的全面崩盘的状况。

3.2.2 事中:

ehcahe本地缓存 + Hystrix限流&降级,避免DB被打死

使用ehcahe本地缓存的目的也是考虑在redis集群彻底不可用的时候,ehcahe本地缓存还能支撑一阵。

使用Hystrix进行限流&降级,好比一秒来了5000个请求,咱们假设只能有一秒2000个请求经过这个组件,那么其余3000个请求就会走限流逻辑。

而后去调用咱们本身开发的降级组件,好比设置一些默认值之类的,以此来保护DB不会被大量请求搞的宕机。

3.2.3 过后:

开启redis的持久化机制,恢复缓存服务器集群

缓存服务器重启,根据配置的持久化策略,会读取日志文件,恢复内存中的数据。

4 解决热点数据集中失效的问题

咱们在设置缓存的时候,通常也会设置缓存的失效时间,过了这个时间,缓存失效了。

若是这批数据,是请求量比较高的,那么请求就会转到数据库去,数据库压力瞬间增大,性能降低甚至宕机。

就是缓存击穿现象。

4.1 解决办法

4.1.1 设置不一样的失效时间

避免热点数据集中失效,在设置缓存时间时,咱们让它们的失效时间错开。好比在一个基础的时间上加上或减去一个范围内的随机值。

4.1.2 互斥锁

结合上面提到的请求,在高并发请求中,在第一个请求去查询数据库的时候对它加一个互斥锁,其他的查询请求都会被组塞住,直到锁被释放,从而保护数据库。

可是也是由于它会阻塞其余线程,系统的吞吐量也会降低,须要结合业务中的实际须要来考虑要不要这么作。

相关文章
相关标签/搜索