现在互联网项目,为了提升数据访问和操作效率,会在架构设计加上缓存系统,目前最常见的是redis 。引入缓存系统没有问题,不过下面的这些问题,你考虑到了吗?或者说你遇到了吗?今天的主题是缓存系统四连击。
1,缓存穿透
遇到的第一个问题应该会是“缓存穿透”,缓存穿透:当请求访问一个缓存系统和数据库都不会存在的数据,是会造成改请求先访问缓存系统,发现不存在,然后再去数据库查询,发现还是没有,再返回响应。如果遇到大量的“不存在数据”的访问请求,则会将压力直接无效的先打到缓存系统,再打到数据库上。再比如有人恶意拿着大量的不存在的userId请求系统,会造成缓存系统和数据库压力剧增,甚至崩溃,这时你该怎么办?
数据存不存在,是得先去查了才知道啊,这没啥毛病啊,正常不都这么走吗?
对,没错,上面的也就是这流程才造成“不存在数据”直接压到数据库,所以有时候就是正常流程惹的祸,具体要看业务,来决定问题大小,并解决。
解决方案:我们最终的目的是减小数据库压力,让数据不存在的直接不访问到数据库就好了,那怎么做?
(1)缓存系统为不存在的数据,设置默认值或者空值
(2) 上面(1)方案是解决了数据库的压力,但缓存系统的压力还存在,想继续解决怎么办?简单啊,不让他压到缓存系统就行了。在访问缓存系统前,先判断该数据是否存在,如果不存在也直接返回。那主要就是“判断数据是否存在”服务了,这个具体可以看一下我之前的文章《【4分钟算法系列】在10亿数据中判断数据是否存在》(之前就说过我写的文章都是为了后面的做铺垫的,所以连续起来看,你会看到更多的东西)
2,缓存击穿
缓存击穿:当大量请求访问同一个数据时,而恰好这个数据刚好已经失效,那么请求全部会压到数据库。遇到的第二个问题就是缓存击穿了,这也是一般不常想到的,高并发的时候会遇到,所以高并发时,这点你需要结合业务考虑下。
解决方案:我们的最终目的还是减少数据库的压力,上面“不存在数据”可以全部断送在访问缓存系统和数据库途中,可现在是这些数据是存在的,只是缓存失效了,那得访问数据库了,怎么办?
(1)现在访问数据库是必然的,不过我们可以减少次数,第一个访问缓存系统的该数据,发现该数据失效,则先加锁再访问数据库获得最新数据,然后缓存数据到缓存系统,并且返回响应,那么接下来的访问缓存系统该数据的请求就没有失效了,会直接从缓存系统获取到值,不会再访问数据库。留个问题,第一个发现失效的,为什么要加锁再去访问数据库?
3,缓存雪崩
在高并发的情况下,由于某种原因,导致大量的缓存值访问不到,请求直接压到数据库,这就是缓存雪崩。比如缓存系统崩了,大量的请求直接压到数据库,数据库压力剧增,甚至崩溃,这时该怎么办呢?
解决方案:既然是崩,那就不让他崩,并且崩了也减少数据库的压力,这是两个步骤,一是缓存系统尽可能高可用,二是缓存系统崩了以后,减少数据库压力
(1)缓存系统集群处理(可以看下我之前文章有redis解决问题章节),然后加上限流机制服务(或者更多点:限流降级熔断机制服务),限流服务可以自研,或者第三方如hystrix 比如只放2000请求到数据库,其余的其他处理
4,热点数据集中失效
这一个也是经常被忽视的,缓存系统缓存的数据都是有过期时间的,但要是同一时刻,高并发场景,大量的请求数据都全部失效了,那请求会全部压到数据库,数据库压力剧增,甚至down,这就是热点数据集中失效。那这种怎么解决呢?
解决方案:既然是数据集中失效了,那不让它集中失效了,就行了。
(1)缓存系统新增数据时,过期时间加一个随机值(不一定加随机值,可以其他机制也行,不然过期时间一样就行),预防同一时刻插入大量的数据过期时间相同或者接近,而后续造成热点数据集中失效问题。
5,总结
本文介绍了缓存系统四连击问题和解决方案,这些方法只是一种,希望能给大家一些思路,大家都可以学学,但一定要结合业务来用,是技术服务于业务,业务推动技术,所以技术方案不要脱离了业务。
点个赞吧……