Redis缓存三剑客:穿透、击穿、雪崩一文讲清楚

0 阅读5分钟

Redis缓存三剑客:穿透、击穿、雪崩一文讲清楚

引言:

Redis缓存这一技术在软件开发领域应用广泛,且是面试常考题,而其中又数缓存三剑客:穿透、击穿、雪崩最为常见,几乎是必考题,所以在学完Redis后,不管是应对面试官的拷问还是为了以后提高自己写代码的质量,了解缓存三剑客发生的原因和解决方法都非常重要,下面跟着小编用一种通俗的视角来了解一下吧。

什么是缓存?

缓存顾名思义其实就是将一部分需要经常访问的数据提前拿出来,放到一个地方。

在没有缓存前,客户端的请求直接打到数据库,而数据库属于磁盘操作,速度较慢,若短时间内的请求过多,就会造成数据库压力过大而挂掉。

而Redis就是基于内存存储的一种非关系型数据库,引入了Redis缓存后,相当于在数据库前面筑起一道墙,客户端的请求打到Redis,发现没有缓存,才会请求数据库,将磁盘中的数据放到内存中,下次再有请求访问相同数据时,直接在内存中读取,大大提高了请求处理的效率。

但缓存也并非无懈可击,在此处可以对接下来要阐述的缓存问题下个定义,那就是:

**缓存中的某个、某些或Redis本身的突然失效,导致大量的请求在一瞬间砸到数据库所产生的一系列问题,**而缓存三剑客就是其中最常见的三个问题

带着这句话去理解接下来具体的情况,你会感觉更加通透,一通百通。

表格总览

问题触发条件核心困扰解决思路
缓存穿透数据根本不存在请求每次都打到数据库拦截不存在数据
缓存击穿(热点key)一个热点key过期此热点key的请求集中到了数据库对重建过程进行控制
缓存雪崩大量key同时过期或Redis服务宕机大量请求同时打到数据库分散压力、提高可用性

缓存穿透

发生原因:

客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,所有请求就都打到了数据库

解决方案:

1.缓存空对象

思路:将不存在的数据也建立在Redis中,值设为空,并设置一个较短的TTL(过期时间)

优点:实现简单,维护方便

缺点:缓存空对象有额外内存消耗,存在短期不一致问题(缓存未过期之前,数据库中创建了此数据,造成不一致问题,过期后问题消失)

2.布隆过滤器

思路:利用布隆过滤算法,在请求进入Redis前判断数据是否存在,若不存在直接拒绝请求

优点:内存占用低

缺点:实现复杂,存在误判的可能(属于漏判,但不会所杀无辜,会有少量数据漏过,可以结合方案1一起实现)

其他

做好基础的格式校验(由前端先拦截一部分)

加强用户权限校验

做好热点参数的限流(分布式环境中涉及)

缓存击穿(热点key问题)

发生原因:

热门访问数据(热点key)在缓存中突然失效,且重建耗时较长,短时间内大量请求打到数据库,产生巨大压力

解决方案:

1.互斥锁

思路:给缓存的重建过程加锁,确保数据的重建过程只有一个线程去执行,其他线程阻塞等待,重建完成后获取新数据

优点:实现简单,没有额外内存消耗,一致性好(重建期间其他线程没有任何操作)

缺点:阻塞等待会导致性能下降,且有死锁风险(获取锁的线程需要调用另一个方法,但如果发现那个锁被取走,就会陷入阻塞等待,若锁的依赖关系闭环就会陷入死锁,可通过设置TTL来缓解)

2.逻辑过期

思路:热门key设置永不过期,这样先保证请求不会打到数据库,而Redis里为此热门key设置一个逻辑上的过期时间,在请求查询到数据时计算缓存当前的存在时长,判断其是否超过了TTL,以此来决定是否需要重建缓存;重建缓存时也可以用互斥锁保证单线程执行,防止并发问题;并且独立创建出一个线程去异步执行重建,而其他线程直接返回旧数据

优点:异步操作,线程无需等待,性能较好

缺点:不保证一致性,有额外内存消耗,实现复杂

使用场景:B站的视频播放量(大V视频会出现1播放多点赞的情况,高频访问的播放量数据在你主动刷新前会先返回你旧的数据),高并发秒杀

缓存雪崩

发生原因:

短时间内缓存中大量key同时失效或Redis服务宕机,导致大量请求打到数据库,产生巨大压力

解决方案:

1.给不同的key加上随机的TTL(解决大量key同时失效)

2.利用Redis集群提高服务的可用性(主从集群:主节点挂了有从节点快速顶上,其利用了烧饼机制)

3.给缓存业务添加降级限流的策略(2、3方案合称开源节流)

4.添加多级缓存(遇事不决就加一层,给Redis也加了层墙)

注:这部分除方案1外都是有关于提高服务可用性的进阶知识,推荐有一定分布式基础后再尝试去理解

尾言:

在实践当中,为Redis里的key设置合理的TTL可以解决初级阶段里接触到的绝大多数问题,也是一个兜底的好手,但不能对此形成依赖,在高并发环境下,缓存中的数据突然过期则可能会引发并发问题,这部分在有基础了之后再研究吧。