提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
提示:这里可以添加本文要记录的大概内容:
- 随着移动互联⽹的快速发展,互联⽹的⽤户数量越来越多,产⽣的数据规模也越来越⼤,对数据库也提出了更⾼的要求,为了减少直接访问数据库,我们会⽤ Redis 作为缓存层。
-
- 因为 Redis 是内存数据库,我们可以将数据库的数据缓存在 Redis ⾥,相当于数据缓存在内存,内存的读写速度⽐硬盘快好⼏个数量级,这样⼤⼤提⾼了系统性能。
- 在今天的互
联⽹⾥,⾼并发、⼤数据量、⼤流量已经成为了代⾔词,那么我们的系统也承受着巨⼤的压⼒,⾸当其冲的解决⽅案就是 redis 。 - redis 使⽤不当就会产⽣雪崩、穿透、击穿等问题
一、缓存雪崩
通常: 为了保证缓存中的数据与数据库中的数据⼀致性,会给 Redis ⾥的数据设置过期时间,当缓存数据过期后,⽤户访问的数据如果不在缓存⾥,业务系统需要重新⽣成缓存,因此就会访问数据库,并将数据更新到Redis ⾥,这样后续请求都可以直接命中缓存。

雪崩原因: ⼤量数据同时过期 / Redis 故障宕机

- 当⼤量缓存数据在同⼀时间过期(失效)或者 Redis 故障宕机时,这时⼤量的⽤户请求,就直接访问到数据库了,从⽽导致数据库的压⼒骤增,严重的会造成数据库宕机,从⽽造成整个系统崩溃,这就是造成缓存雪崩的原因。
- 总结:在⾼并发下,⼤量缓存 key 在同⼀时间失效,⼤量请求直接落在数据库上,导致数据库宕机。
解决方法:
- ⼤量数据同时过期时 解决方法:
| 方法 | 解释 |
|---|---|
| 均匀设置过期时间 | 避免将⼤量的数据设置成同⼀个过期时间。在对缓存数据设置过期时间时,给这些数据的过期时间加上⼀个随机数,这样就保证数据不会在同⼀时间过期。 |
| 互斥锁 | 请求时,如果发现访问的数据不在 Redis ⾥,就加个互斥锁,保证同⼀时间内只有⼀个请求来构建缓存,但容易阻塞,系统会出现无响应现象 |
| 双 key 策略 | 对缓存数据可以使⽤两个 key ,⼀个是主 key ,会设置过期时间,⼀个是备 key ,不会设置过期。当业务线程访问不到 主key 的缓存数据时,就直接返回 备key 的缓存数据,然后在更新缓存的时候,同时更新 主key 和 备key 的数据。 |
| 后台更新缓存 | 业务线程不再负责更新缓存,缓存也不设置有效期,⽽是让缓存“永久有效” |
- Redis 故障宕机 解决方法:
① 服务熔断或请求限流机制(雪崩发⽣后的应对⽅案)
服务熔断机制:(全部业务都⽆法正常⼯作)
暂停业务应⽤对缓存服务的访问,直接返回错误,不⽤再继续访问数据库,从⽽降低对数据库的访问压⼒,保证数据库系统的正常运⾏,然后等到Redis 恢复正常后,再允许业务访问缓存服务。
请求限流机制:(减少对业务的影响)
只将少部分发送到数据库进⾏处理,再多的请求就在⼊⼝直接拒绝服务,等到 Redis 恢复正常并把缓存预热完后,再解除请求限流的机制。
② 构建 Redis 缓存⾼可靠集群
通过主从节点的⽅式构建 Redis 缓存⾼可靠集群。
如果 Redis 缓存的主节点故障宕机,从节点可以切换成主节点,继续提供缓存服务,避免了由于 Redis 故障宕
机⽽导致缓存雪崩问题。
二、缓存击穿
**击穿原因:**如果缓存中的某个热点数据(被频繁地访问的数据)过期了,此次⼤量的请求访问了该热点数据,就⽆法从缓存中读取,直接访问数据库,数据库很容易就被⾼并发的请求冲垮,这就是缓存击穿的问题。(可以认为缓存击穿是缓存雪崩的⼀个⼦集)
解决方法:
- 互斥锁⽅案,保证同⼀时间只有⼀个业务线程更新缓存,未能获取互斥锁的请求,要么等待锁释放后重新读取
缓存,要么就返回空值或者默认值。 - 不给热点数据设置过期时间,由后台异步更新缓存,或者在热点数据准备要过期前,提前通知后台线程更新缓
存以及重新设置过期时间。
三、缓存穿透
穿透原因:
当⽤户访问的数据,既不在缓存中,也不在数据库中,导致请求访问缓存时,发现缓存缺失,再去访问数据库时,发现数据库中也没有要访问的数据,⽆法构建缓存数据来服务后续的请求。那么当有⼤量这样的请求到来时,数据库的压⼒骤增,这就是缓存穿透的问题。
- 业务误操作,缓存中的数据和数据库中的数据都被误删除了,所以导致缓存和数据库中都没有数据。
- ⿊客恶意攻击,故意⼤量访问某些读取不存在数据的业务。
解决方法
| 方法 | 解释 |
|---|---|
| ⾮法请求的限制 | 在 API ⼊⼝处我们要判断请求参数是否合理,请求参数是否含有⾮法值、请求字段是否存在,如果判断出是恶意请求就直接返回错误,避免进⼀步访问缓存和数据库。 |
| 缓存空值或者默认值 | 针对查询的数据,在缓存中设置⼀个空值或者默认值,这样后续请求就可以从缓存中读取到空值或者默认值,返回给应⽤,⽽不会继续查询数据库。 |
| 布隆过滤器 | 使⽤布隆过滤器快速判断数据是否存在,避免通过查询数据库来判断数据是否存在。我们可以在写⼊数据库数据时,使⽤布隆过滤器做个标记,缓存穿透时,可以通过查询布隆过滤器快速判断数据是否存在,如果不存在,就不⽤通过查询数据库来判断数据是否存在。 |
总结
雪崩是⼤⾯积的 key 缓存失效;
穿透是 Redis ⾥不存在这个缓存 key ;
击穿是 Redis 某⼀个热点 key 突然失效,最终的受害者都是数据库。


1万+

被折叠的 条评论
为什么被折叠?



