缓存崩溃
作者:w08e
redis实战之各种崩溃 雪崩 击穿 穿透 以及预热
缓存雪崩
回答话术
缓存雪崩是应用系统指在某个时间点上,缓存中的大部分数据同时失效,导致大量的请求直接访问底层数据库或后端服务,从而造成数据库负载剧增,甚至导致数据库崩溃的情况。
通常情况下,缓存中的数据会设置不同的过期时间,以避免同时失效的情况。然而,如果某个不可控的事件导致了大量缓存同时失效,就会出现缓存雪崩。
需要从以下几个方面去解决缓存雪崩问题:
1. 设置不同的过期时间
可以通过设置随机过期时间或者固定过期时间引入随机偏移量两种方案,一定程度上缓解缓存雪崩问题。,集群部署也可以把热点数据放到不同的服务。
2. 缓存预热
在系统启动或者某个特殊节点前,将热门数据预先加载到缓存中,避免在高并发或者其他情况数据不在缓存还需额外请求数据库加载的情况。
3. 设置部分key永不过期
对于一些热点数据,可以设置永不过期,以保证这部分数据始终在缓存中可用。同时,需要保障缓存设置的内存淘汰策略是不淘汰或者从带过期时间 Key 中去淘汰。
- 电商系统:比如需要参加秒杀的商品数据,我们为了避免因设计过期时间自动过期或者不合适的 Redis 过期策略自动清楚,需要将参与秒杀的商品数据直接设置为永不过期。
缓存穿透
回答话术
缓存击穿指在高并发的系统中,一个热点数据缓存过期或者在缓存中不存在,导致大量并发请求直接访问数据库,从而给数据库造成巨大压力,甚至可能引起宕机。
具体来说,当某个热点数据在缓存中过期时,如果此时有大量并发请求同时访问这个数据,由于缓存中不存在,所有请求都会直接访问数据库,导致数据库负载急剧增加。
一般来说,解决缓存击穿的主要方法分为三种:热点数据永不过期、热点数据预加载以及加分布式锁。
1. 热点数据预热
在活动开始之前,就将已知热点数据加载到缓存中,避免出现第一次请求直接打到数据库的情况。
2. 数据永不过期
热点数据永不过期,指的就是可以预知的热点数据,在活动开始前,设置过期时间为 -1。这样的话,就不会有缓存击穿的风险。
这个可以搭配热点数据预加载一起完成。等对应热点缓存的活动结束后,这些数据访问量就比较低了,可以通过后台任务的方案对指定缓存设置过期时间,这样可以有效降低 Redis 存储压力。
3. 分布式锁
分布式锁的解决方案就是保证只有一个请求可以访问数据库,其它请求等待结果。这样可以避免大量的请求同时访问数据库。
ps: 分布式锁需要注意双检查,也就是获取到锁后需要再次尝试从缓存中获取数据,避免等待锁的请求再次查询db。
特殊情况也可以考虑
trylock
直接报错 而不是一直阻塞等待锁。
缓存击穿
回答话术
缓存穿透是指由于请求没有办法命中缓存,因此就会直接打到数据库,当请求量较大时,大量的请求就可能会直接把数据库打挂。
通常情况下,缓存是为了提高数据访问速度,避免频繁查询数据库。但如果攻击者故意请求缓存中不存在的数据,就会导致缓存不命中,请求直接访问数据库。
简单的情况 比如数据主键是自增的,如果某个请求是负数或者id为特别大的,缓存没有 大量请求到db 有可能给db打挂。
缓存穿透通常有几种解决办法: 参数检验空值缓存、锁、布隆过滤器;
1. 参数校验,空值缓存
对一些非法的参数做一些校验,比如-1直接 return了 不去查询redis或者db,
当查询结果为空时,也将结果进行缓存,但是设置一个较短的过期时间。这样在接下来的一段时间内,如果再次请求相同的数据,就可以直接从缓存中获取,而不是再次访问数据库,可以一定程度上解决缓存穿透问题。
不过这种方式也有小问题,这种方式同时也会在短时间内会造成缓存系统大量的内存占用,彻底解决这种海量恶意请求还是需要一套风控系统。
2. 加锁
当请求发现缓存不存在时,可以使用锁机制来避免多个相同的请求同时访问数据库,只让一个请求去加载数据,其他请求等待。
这种方式可以解决数据库压力过大问题,如果会出现“误杀”现象,那就是如果缓存中不存在但是数据库存在这种情况,也会等待获取锁,用户等待时间过长,不推荐使用。
3. 布隆过滤器
布隆过滤器是一种数据结构,可以用于判断一个元素是否存在于一个集合中。它可以在很大程度上减轻缓存穿透问题,因为它可以快速判断一个数据是否可能存在于缓存中。
这种方式较为推荐,可以将所有存量数据全部放入布隆过滤器,然后如果缓存中不存在数据,紧接着判断布隆过滤器是否存在,如果存在访问数据库请求数据,如果不存在直接返回错误响应即可。
简单来说他因为你对你不一定对 存在误差率,但是他认为你错就一定错。
5. 组合使用 布隆过滤器+空对象+分布式锁
上面的这些方案或多或少都会有些问题,应该用三者进行组合用来解决缓存穿透问题。
如果说缓存不存在,那么就通过布隆过滤器进行初步筛选,然后判断是否存在缓存空值,如果存在直接返回失败。如果不存在缓存空值,使用锁机制避免多个相同请求同时访问数据库。最后,如果请求数据库为空,那么将为空的 Key 进行空对象值缓存。
缓存预热
聊完缓存常见的问题,现在聊聊预热,上面三个常见问题雪崩和击穿都可以通过预热解决,让我们分析一下。
回答话术
缓存预热是在系统启动或者运行过程中,提前将部分数据加载到缓存中,以确保在实际请求到来时,缓存已经包含了部分常用数据,从而提升系统的响应速度。
可以使用项目启动预热 或者xxjob定时或者把需要预热的消息放到消息队列然后通过消费者线程从消息队列中获取数据,并执行相应的数据读取流程最终存储到 Redis 中。
标签:缓存,请求,过期,数据库,redis,预热,崩溃,数据 From: https://www.cnblogs.com/w08e/p/18389127