我们日常开发过程中,或多或少都是使用到缓存,通过缓存来实现提升接口响应速度。其中使用Redis作为缓存组件是最常见的技术选型,使用Redis优势很多,但是其存在过程中常见三大问题:缓存穿透,缓存击穿,缓存雪崩,我们也需要有所掌握,并且需要知道怎么解决。
1. 缓存穿透
缓存穿透是指前端请求到达后端服务器后,先从Redis缓存中查询,没有查询到结果,然后查询数据库,数据库查询不到数据则不进行数据缓存。流程图示如下
这种在代码逻辑上会先查询Redis,再查数据库。逻辑上Redis有一层缓存,但是实际情况却是Redis并未起到缓存的真是作用,使得请求全部进入数据库查询,数据库也没有查询到数据,数据库没有查询到数据之后也没有进行空对象写入缓存。这种情况,称之为缓存穿透!在低并发情况下,数据库可以承受住压力的话。存在缓存穿透对系统影响不大,但是在高并发的场景下,大量请求对数据库会造成很大的压力,极有可能直接数据库宕机影响系统的使用,这种是需要极力避免的。处理办法有常见的两种,数据库查询后缓存和布隆过滤器
1.1 数据库查询后缓存
数据库查询后缓存是指,请求先通过Redis查询,没有查询到数据,然后请求查询数据库,将数据库查询结果进行Redis缓存,然后响应前端请求。这种是数据库数据存在数据的场景,一次查询后缓存,后续相同数据查询就会走Redis。另外一种是数据库也不存在对应的数据,这时,数据库为查询到数据,也将null缓存到Redis中。这样后续的请求也是会走到Redis中。但是这种方式存在很大的弊端,请求第一次还是会进入数据库,在高并发的情况下,数据库压力其实也很大。一般不采用这种方式处理。这种请求的图示如下
1.2 使用布隆过滤器
布隆过滤器的相关知识,就不在这里说明了,可以参考一下我关于布隆过滤器的理解的文章。布隆过滤器文章。根绝布隆过滤器的特点,如果布隆过滤器判定没有,就一定没有,可以帮助服务端过滤非法数据的请求,即Redis没有相关,数据库也没有相关数据的请求。布隆过滤器的作用效果图示如下:
在使用布隆过滤器的时候,有个前置条件,就是需要将校验数据提前在布隆过滤器中进行存储。当布隆过滤器判断请求的数据不存在时,直接返回响应,避免对数据库造成很大的压力。以上是处理缓存穿透的两种常见的处理方案。
2. 缓存击穿
系统中都存在某个或许某些热点数据,访问量特别大,当大量请求进入服务器后,遇上缓存失效,缓存不存在导致大量的直接访问数据库,给数据库造成过大的压力,称为缓存击穿。处理换缓存击穿常见的处理有两种方案。合理的设置热点数据过期时间和加锁访问。
2.1 合理设置热点数据过期时间
热点数据在缓存的时候,根据实际的业务常见,估算充裕的缓存的失效时间,例如某个活动的投放时间是10个小时,这10个小时候的访问量肯定较大。但是10个小时候,就可以保证并发量一定会出现大幅下降吗?我个人觉得不一定。所以我们在设置这个热点key的过期时间是,可以设置20小时,甚至24小时。这样会更加的保险。具体的时间还得根据具体的场景设置。
2.2 加锁访问
热点数据设置合理的过期时间,是一个有效方案,但是这个方案对系统压力还是很大。此时为了保护系统的稳定性,还需要有其他的手段来处理,加锁访问就是一种比较有效的手段。加锁的方式有很多种,如果是单节点,Java自带的synchronized就可以实现,但实际情况往往不大可能。现在都是集群部分来保证服务的高可用性。所以在加锁时,需要使用分布式锁。可以使用比较常用,例如:redisson等。
以上是个人总结的为了防止缓存击穿,导致数据库压力过大,影响系统的稳定性的处理方案!
3. 缓存雪崩
缓存雪崩,字面意思也比较好理解,就是缓存的数据出现雪崩。大面积的缓存数据或者所有的缓存数据都失效,所有的请求全部进入数据库查询的情况。缓存雪崩实际上不大可能是程序问题,更大的概率是由于其他因素导致,例如服务器断电等等。处理缓存雪崩,我个人认为更多的是得从运维的角度来处理,比如服务器集群部署,服务器多区域部署。另外还可以通过服务降级,服务限流等方面入手处理。
以上就是个人针对使用Redis缓存时,会遇到的三大问题的分析与常见的处理方案了,如有其他更加优秀的处理方案,欢迎讨论!!!