Redis缓存雪崩、击穿、穿透
一、缓存三大问题
这三个问题一旦发生,就会导致大量请求进入后台的数据库,如果有大量并发同时到达数据库,有可能会导致数据库宕机,影响业务,也有可能会导致一系列连锁反映,很可能导致业务长时间无法恢复。
接下来本文详细介绍这三个问题的发生场景以及对应的解决方案。
二、缓存雪崩
2.1 雪崩场景
雪崩是指大量请求无法在redis进行处理,原本预期在redis的中存在的数据却在redis中不存在,紧接着这些请求被全部转发到了数据库,导致暑数据库压力大增。产生雪崩的原因主要有两个:
- 缓存中有大量的数据同时过期,导致大量请求无法在redis中无法处理。
- Redis宕机
2.1 应对方案
针对缓存中有大量的数据同时过期的应对方案
- 避免给大量业务数据设置相同的过期时间,业务场景中总会出现同时实效的case,比如基于订单的下单时间。对于这种场景,可以在过期时间后面加个随机的时间比如(1-3分钟)。这样既保证了业务基本在相近的时间过期,也不会在同时间集中过期。
- 降级,如果雪崩已经产生,可以对业务进行降级,非核心数据直接返回指定的静态数据(缓存中没有也不去数据库请求),只有核心数据持续访问缓存(如果缓存没有,也可以去访问数据库,由于限制了非核心数据的请求,这个时候db的压力应该不大)。
针对Redis宕机应对方
redis宕机就等于所有数据同时失效,等于最强雪崩,redis所能承载的qps是万级别,而单个数据库所能承载的qps是千级别,这个时候如果所有请求全部进入DB,必然会导致DB的奔溃。有两个处理方法。
-
服务彻底熔断,当前进来后直接返回,不再访问数据库,对服务使用方来说,整个服务是不可用的,对业务的影响最大,但是彻底保护了数据库。
-
请求限流,在业务系统的请求入口控制每秒进入服务的次数,限流的比例可以基于之前的数据进行分析,比如在雪崩前入口的qps是10000,其中9000被redis承载,1000进入了数据库(说明数据库能承载1000的qps),那么这个时候可以将入口的qps 限制为1000,这样既保证了数据库的安全,也不至于业务不可用(部分可用状态)。限流示意图如下。
-
主从集群部署,实现redis的高可用,当主节点宕机后从节点可以切换为主节点继续提供服务。
当然宕机后的一系列处理方法同样适用于大量key同事过期的case。
三、缓存击穿
3.1 击穿场景
热点数据在redis中找不到,和雪崩相比,击穿对应的热点数据数据量比较小,但是这些数据的请求量非常高,导致大量请求都被大到了数据库。
击穿发生在热点数据失效时。
3.2 应对方案
对于缓存击穿解决方案比较简单,对于热点数据可以设置永不过期,这样就解决了失效问题。
四、缓存穿透
4.1 穿透场景
缓存穿透是指查询的数据既不在缓存也不在数据库,请求redis时候发现缓存缺失,再去访问数据库,发现数据库也没有,所以无法补全缓存数据,导致每次查询都会去请求数据库,当有
大量类似的请求场景时候,也会对数据库造成巨大的压力。
发生穿透的场景:
- 业务误操作导致本应该存在的数据被误删除
- 恶意攻击,专门查询数据库中没有的数据,利用穿透的漏洞。
- 设计问题,代码不严谨,已知可能为空的数据没有去做判断。
4.2 应对方案
有三个方法可以解决穿透问题。
- 给缓存赋空值或者缺省值,一旦发现没有业务数据,可以赋为空置或者留一个标示值,比如有值的时候对应的值是一个list,如果发现没有业务数据可以付一个空的list,这样等下次再来访问时,发现redis已经有缺省值,可以直接返回,避免了多次访问数据库。
- 通过业务规则判断,如果通过某些规则就可以知道没有数据,则可以直接不用访问。
- 使用布隆过滤器,可以快速判断数据是否存在,避免从数据库中查询是否存在,减轻数据库的压力。原理和相关使用后期专门写一篇文章介绍。
本文完。