文章目录
- Redis 的缓存雪崩、击穿、穿透及其解决办法
- 缓存雪崩
- 解决办法
- 缓存击穿
- 解决方案
- 缓存穿透
- 解决方案
Redis 的缓存雪崩、击穿、穿透及其解决办法
本篇文章回顾 Redis 当中缓存崩溃、击穿、穿透现象以及相应的解决办法,主要的参考资料是:https://www.csview.cn/redis/application.html。
缓存雪崩
当大量 Redis 中的数据同时过期或 Redis 宕机时,如果此时恰好有大量的用户请求,由于 Redis 无法处理这些请求,请求直接访问数据库,从而使得数据库的压力骤升,严重情况下会导致数据库宕机,进而导致整个服务崩溃。
解决办法
针对大量数据同时过期
- 均匀设置过期时间:以避免大量数据同时过期;
- 互斥锁:业务线程处理用户请求时,如果发现数据不在 Redis 中,就加互斥锁,保证同一时间内只有一个请求在构建缓存。未能获取互斥锁的请求等待锁释放后重新读取缓存,或返回空值或默认值。
- 双 key 策略:设置一个主 key 和一个备 key,当主 key 访问不到数据时,请求到备 key 寻找数据。主 key 设置过期时间,而备 key 不设置过期时间,缓存更新时,同时更新两个 key 中的 value。
- 后台更新缓存:业务线程不再负责更新缓存,缓存也不设置有效期,而是让缓存“永久有效”,更新缓存的工作交给后台线程定期完成。
针对 Redis 故障宕机
- 服务熔断或限流请求:启动服务熔断机制,暂停业务应用对缓存服务的访问,直接返回错误。服务熔断之后暂时不会有请求访问数据库,保证数据库系统的正常运行。Redis 恢复正常后,再允许业务应用访问缓存服务。也可以启用限流机制,只将少部分请求发送到数据库处理。
- 构建高可靠集群:通过主从结点的方式构建 Redis 缓存高可靠集群。如果 Redis 缓存的主结点宕机,则从结点切换为主结点继续提供缓存服务,避免由 Redis 宕机导致的缓存雪崩问题。
缓存击穿
如果缓存中某个热点数据过期,此时大量的请求访问热点数据,就无法从缓存直接读取了,而是直接访问数据库,数据库很容易因大量的高并发请求而被冲垮。
解决方案
- 互斥锁:保证同一时间只有一个业务线程更新缓存,未能获取互斥锁的请求,要么等待锁释放后重新读取缓存,要么返回空值或默认值。
- 不给热点数据设置过期时间。
缓存穿透
当用户访问的数据,既不在缓存中,也不再数据库中,导致请求在访问缓存时,发现缓存中数据丢失,进而去数据库查找数据,发现没办法构建缓存,来服务后续的请求。当有大量这样的请求到来时,会导致数据库的压力骤增,这就是缓存穿透问题。
解决方案
- 非法请求的限制:当有大量恶意请求访问不存在的数据时,就会发生缓存穿透。可以在 API 入口处判断请求是否合理,如果判断出是恶意请求,就直接返回错误,避免该请求进一步访问缓存或数据库。
- 缓存空值或默认值:当线上业务发现缓存穿透现象时,可以针对查询的数据,在缓存中设置一个空值或默认值,这样后续的请求就可以从缓存中获取空值或默认值,进而不会再继续去访问数据库了。
- 使用布隆过滤器快速判断数据是否存在,避免通过查询数据库来判断数据是否存在:写入数据库时,使用布隆过滤器做标记,然后在用户请求到来时,业务线程确认缓存失效后,通过查询布隆过滤器快速判断数据是否存在。如果数据不存在,就不需要查询数据库了。