redis的缓存穿透|缓存击穿|缓存雪崩

158 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情

redis的异常场景类型: image.png

在实际生产环境中有时会遇到缓存穿透、缓存击穿、缓存雪崩等异常场景,为了避免异常带来巨大损失,我们需要了解每种异常发生的原因以及解决方案,帮助提升系统可靠性和高可用。

一、缓存穿透。

什么是缓存穿透?

缓存穿透是指用户请求的数据在缓存中不存在即没有命中,同时在数据库中也不存在,导致用户每次请求该数据都要去数据库中查询一遍,然后返回空。

解决方案:

1、参数合法性校验

如果是有意义的参数值,进行合法性校验(比如手机号码),防止恶意攻击。

2、布隆过滤器

布隆过滤器(Bloom Filter,简称BF)是一种空间效率高的概率型数据结构。布隆过滤器专门用来检测集合中是否存在特定的元素。把所有数据加载布隆过滤器中,交由布隆过滤器判断处理。

布隆过滤器底层使用bit数组存储数据,该数组中的元素默认值是0。布隆过滤器第一次初始化的时候,会把数据库中所有已存在的key,经过一些列的hash算法(比如:三次hash算法)计算,每个key都会计算出多个位置,然后把这些位置上的元素值设置成1。

有关布隆过滤器的问题,后续会有专门的文章讲解。

3、返回空对象

当缓存未命中,查询持久层也为空,可以将返回的空对象写到缓存中,这样下次请求该key时直接从缓存中查询返回空对象,请求不会落到持久层数据库。为了避免存储过多空对象,通常会给空对象设置一个过期时间。

二、缓存击穿。

什么是缓存击穿?

缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。

解决方案:

1、使用互斥锁(mutex key)

让一个线程回写缓存,其他线程等待回写缓存线程执行完,重新读缓存即可。

2、热点数据不设置过期时间,或者通过异步线程进行失效时间的续期。

三、缓存雪崩。

什么是缓存雪崩?

缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,请求直接落到数据库上,引起数据库压力过大甚至宕机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。

解决方案:

1、加互斥锁

跟缓存击穿解决思路一致,同一时间只让一个线程构建缓存,其他线程阻塞排队。

2、缓存永不过期

跟缓存击穿解决思路一致,缓存在物理上永远不过期,用一个异步的线程更新缓存。

3、缓存均匀过期

设置不同的缓存失效时间,尽量做到均匀分布,随机分布,不能再同一个时间设置大量失效key,也不能再业务高峰时期,失效大量key,尽量避免。

四、缓存预热

缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统,这样就可以避免在用户请求的时候,先查询数据库,然后再将数据回写到缓存。

缓存预热的操作方法:

当数据量不大的时候,工程启动的时候加载数据到缓存;

当数据量大的时候,可以通过定时脚本,进行缓存的刷新。

五、缓存降级

缓存降级是指缓存失效或缓存服务器挂掉的情况下,不去访问数据库,直接返回默认数据或访问服务的内存数据。