当前位置: 首页 > 后端技术 > Java

Redis面试常见问题——缓存雪崩、缓存击穿、缓存穿透

时间:2023-04-01 21:12:39 Java

在开发过程中可能会出现缓存异常。这三个问题会导致大量的请求从缓存中转移到数据库中,如果并发请求量很大,会导致数据库崩溃。所以面试官经常会问这些问题。缓存雪崩缓存雪崩是指大量的请求无法在缓存中处理,从而将请求转移到数据库中,造成数据的双重压力。一个Redis实例可以支持数万个并发请求,而单个数据库只能支持数千个并发请求。两者在处理请求的并发度上相差十倍,数据库会因为压力过大造成雪崩。这里的雪崩一般由两种原因组成。很多文章只写同时过期的缓存。原因一:缓存中大量数据同时过期。一般设置缓存数据都会设置缓存时间。在某一时刻,大量缓存同时过期。如果此时有访问这些数据的请求,缓存不存在,请求会转到数据库中,如果这些请求比较大,会增加数据库的压力,严重的会导致数据库崩溃。大量缓存同时失效导致的雪崩有两种解决方案。方案一:为过期时间设置一个随机值应该避免为数据设置相同的过期时间,在设置过期时间的时候加一点随机值。setRedis(key,value,time+Math.random()*10000);方案二:服务降级服务降级,比如使用hystrix,是指在发生雪崩时,针对不同的数据采用不同的处理方式。如果请求的数据是非核心数据(如商品属性),则暂时停止从缓存中查询数据,直接返回预订信息、空值或错误值。请求的数据是核心数据(比如商品库存,价格),还是查询缓存。如果缓存丢失,则继续从数据库中读取。原因二:redis服务挂了。redis服务宕机,无法处理请求。这会导致所有的请求都转移到数据库中,造成雪崩。方案一:添加服务熔断服务熔断就是在雪崩发生时暂停对缓存的访问。redis服务恢复正常后,允许访问缓存。监控redis所在服务器的指标,比如QPS、CPU占用率、内存占用率等,如果发现redis服务宕机,数据库请求压力成倍增加,可以启动熔断机制挂起访问缓存和数据库,比如使用Hystrix服务熔断器。但是暂停访问缓存系统对整个业务系统的影响很大,导致很多数据无法查看。还有另一种解决方案可以减少这种影响:请求限制。方案二:请求限流请求限流就是限制前端每秒的请求量,让数据库能够承担所有的前端请求。比如前端每秒允许访问1000次,其中900次请求缓存,100次请求数据库。一旦发生雪崩,数据库请求激增到每秒1000次。这时候,请求流量限制就被激活了。前端入口每秒只允许100个请求,太多请求直接拒绝。无论使用服务熔断还是请求限速,都是一个雪崩后的过程,这里也有预防方案。通过主从节点搭建redis集群。如果redis主节点宕机,从节点可以切换为主节点。缓存击穿缓存击穿是指对某个数据频繁访问缓存,无法在缓存中处理。访问数据的请求都是一次请求数据库,导致数据库压力加倍。解决方案一:不设置过期时间。对于访问频繁的热点数据,不要设置过期时间。解决方案2:使用互斥锁。如果缓存失效,只有获取到锁才能访问数据库,减少对数据库的并发访问。缓存雪崩和缓存击穿的区别在于,雪崩是大量的缓存,而击穿是单个缓存。缓存穿透缓存穿透是指访问的数据既不在redis缓存中,也不在数据库中,因为数据库中没有数据,数据库数据无法写入缓存。每个请求都需要缓存和服务器。但是,这也会导致系统性能下降。在以下两种情况下会发生缓存穿透:误操作、删除缓存和数据数据。恶意攻击:专门访问数据库中不存在的数据。方案一:缓存穿透发生在空值或默认值的缓存中。在redis中缓存一个空值或者实现一个预选值(比如0)。后续请求查询直接读取redis中的null或者默认值。方案二:使用BloomfilterBloomfilter由一个初值为0的位数组和N个哈希函数组成,可以用来快速判断某个数据是否存在。当数据写入数据库时??,布隆过滤器会通过三个操作完成标记:使用N个哈希函数分别计算数据的哈希值,得到N个哈希值。将N个哈希值对位数组的长度取模,得到每个哈希值在数组中对应的位置。将对应的位置设置为1。如果数据不存在,那么就不需要使用Bloomfilter来标记数据,那么bit数组对应的bit为0。只要其中一个位数组不为1,就说明布隆过滤器没有标记数据。在向数据库写入数据时,使用布隆过滤器进行标记。当缓存消失后,再去数据库查询之前,先检查布隆过滤器,判断数据是否存在。如果不存在,则不会查询数据库。在请求存储中也增加了检测,直接过滤掉恶意请求(参数不合理、非法参数、参数不存在、id小于0)。电子商务系统实例缓存雪崩*电子商务首页数据(电脑端,移动端)分类等。要设置这种缓存,需要在过期时间上加上一个随机数![](/img/bVcVsBa)缓存突破电商首页猜你喜欢什么,不要设置超时,或者设置互斥![](/img/bVcVsBc)缓存穿透请求非-电子商务产品详细信息中的现有ID。首先设置入口校验,然后使用布隆过滤器。如果没有直接返回总结,缓存雪崩和缓存击穿主要是数据不在缓存中,而缓存穿透是数据既不在缓存上也不在数据上。缓存雪崩过期时间加一个小随机数服务降级服务熔断请求限流Redis设置主从集群缓存击穿无过期时间缓存穿透入口用于合法性验证使用null或默认值使用Bloomfilter最好使用预防性方案快速判断预防性方案的服务缩减、请求熔断、请求限额会影响用户体验。针对缓存雪崩,合理设置数据过期时间,搭建redis主从集群。对于缓存分解,不要设置过期时间。对于缓存穿透,在请求入口处进行标准校验,使用布隆过滤器判断数据是否存在。参考如何解决缓存雪崩、崩溃和穿透问题