当面试官问:你知道什么是缓存击穿吗,你们是如何解决的?
首先我们要了解什么是缓存击穿?以及缓存击穿会引发什么问题?
缓存击穿就是redis中的热点数据过期,缓存失效,导致大量的请求直接打到数据库,进而导致数据库奔溃,整个程序挂掉
那你知道数据库的真实性能是什么样子吗?
我用jmeter对一张500万数据的MySQL表的聚簇索引和普通索引进行了压测,在100个并发下主键索引能有7万的QPS,普通索引也能有2700多的QPS,这还是我自己的PC测出来的数据,不是服务器,jmeter和MySQL还是在同一台机器上的情况。由此可知,MySQL不是可以随意打崩的数据库,这种QPS可能已经可以秒杀全国99%的公司了。
所以,缓存击穿导致数据库奔溃,本质上是一个高并发架构的问题,不是redis本身的问题,redis也是有可能被打崩的。
那么我们应该如何回答这个问题呢?
我觉得缓存击穿这个问题,不能光从redis层面上考虑,做一些永不过期、加锁等方案,而是应该从系统架构方面考虑,比如系统接入缓存监控告警、系统降级熔断策略以及正确评估系统业务量、缓存场景等。
1、正确评估自己系统的容量和业务中的慢sql,做到所有用缓存的场景,哪怕某一时刻所有缓存都失效,你的数据库能力能够承载此时的并发量。对使用缓存的查询用缓存是多少耗时,不使用缓存是多少耗时心中有数。对于TO C场景,就是要讲究查询足够简单,单个查询排除网络因素,要保证耗时在200毫秒以内,哪怕在复杂的场景,在复杂的sql,也要想办法去优化。
2、接入缓存监控告警,一些比较重要的大促级场景,如果等到系统挂了才知道,那绝对是生产事故了。举个例子,秒杀场景你把库存放到了缓存,假如秒杀时间是10分钟的话,这么重要的场景,应该去监控这个库存量和缓存失效时间,在即将过期的时候给个告警或者主动触发一个延时操作。
3、系统降级熔断策略,假如缓存被击穿了,数据库挂了,导致大量请求超时,平均RT也在飙升,此时降级熔断策略应该生效了。举个例子,当你最近100次的请求,平均RT都超过5秒钟了,系统报错率也在飙升,此时应该去熔断对数据库的查询操作,不应该等着全链路上面依赖数据库的请求都挂了,引发生产事故。
当做完这些准备之后,再去谈怎么单纯解决缓存击穿的问题,可以完全忽略那些什么key永不过期的方案,因为一个要去考虑缓存击穿问题的系统,绝对是高并发和海量数据的,如果数据是海量的,不可能把海量数据全部丢到redis里去。当然你可能说你只存热点数据,那什么是热点数据呢?以前微博的架构师做过分享,他们根据长期的业务经验积累,明明知道周一可能会出现热点事件,但是还是阻挡不住,比如某些明星官宣恋情的时候就挂了,所以重要的不是预测,而是做好保底方案。再回到缓存击穿、缓存雪崩、缓存穿透等问题,他们不是redis本身的问题,当然在redis层有一些解决方案,但是这些方案都是有局限性的,应该从系统架构的角度去分析问题,才能有一个更好的解决方案。
缓存击穿图解: