如何解决缓存雪崩、击穿、穿透问题

3,343 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情

前言

Redis作为流行的分布式缓存,在实际生产环境中会遇到缓存穿透、缓存击穿、缓存雪崩等异常场景,为了避免异常带来巨大损失,我们需要了解每种异常产生的原因和对应的解决方案,来提升系统可靠性和可用性。

图片.png

缓存穿透

简介

用户请求的数据在缓存和数据库中都不存在,用户每次请求数据都需要查询数据库,导致对后台数据库的频繁访问,数据库负载压力增大,这种现象就叫做缓存穿透。

产生原因

图片.png

说明:

  • 大量访问不存在的key,导致数据库处理大量请求

解决方案

解决缓存穿透的方法有两种,第一种是缓存空对象,第二种是使用布隆过滤器。

缓存空对象

当数据库中查不到数据的时候,缓存空对象,然后给这个空对象的缓存设置过期时间,下次再查询 数据的时候,直接从缓存中获取,从而达到了减小数据库压力的目的。

方案缺点

  • 需要缓存层提供更多的内存空间来缓存空对象,浪费更多内存空间。
  • 即使在缓存空对象时设置很短的过期时间,也会导致这一段时间内的数据不一致问题。

布隆过滤器

关于布隆过滤器将在后续的文章中详细讲解,本文不进行阐述。

缓存击穿

简介

Redis中存在某些热点数据时,即有大量请求并发访问的key-value数据。当极热点key-value数据突然失效时,缓存未命中引起对后台数据库的频繁访问,这种现象叫缓存击穿。

产生原因

图片.png

说明:热点数据过期,导致大量的查询请求穿过缓存,直接查询数据库。

解决方案

缓存击穿的解决方案有两种,第一种是设置key永不过期;第二种是使用分布式锁,保证同一时刻只能有一个查询请求重新加载热点数据到缓存中,这样,其他的线程只需等待该线程运行完毕,即可重新从Redis中获取数据。

设置key永不过期

在设置热点key的时候,不给key设置过期时间即可。

分布式锁

针对热点key采用分布式锁,当大量查询同一个key的请求时,只能有一个请求获取到锁,查询数据库,然后将结果放入到缓存中,然后释放锁,此时,其他处于锁等待的请求即可继续执行,由于此时缓存中已经有了数据,所以直接从缓存中获取到数据返回,并不会查询数据库。

缓存雪崩

简介

缓存数据在同一个时间点失效,导致大量的请求到数据库,从而使得数据库崩溃

产生原因

图片.png

说明:

  • 第一种为大量Key同一时间过期
  • 第二种为Redis故障

解决方案

针对第一种大量Key同时过期

  • 设置每个key的过期时间尽量不一样,可以在超时时间上添加一个随机时间长度,使它们的失效点尽可能均匀分布。

  • 针对热度数据可以永不过期

针对第二种Redis发生故障

  • 采用Redis的几种高可用方案部署,具体的部署方案可以参考我之前写的Redis的高可用架构。

总结

本文讲解缓存的雪崩、击穿、穿透问题的产生的原因和解决方案,如有疑问,请随时反馈。