大家好,我是锋哥。今天分享关于【Java高频面试题:Redis里什么是缓存击穿、缓存穿透、缓存雪崩?】**面试题。**希望对大家有帮助;

Java高频面试题:Redis里什么是缓存击穿、缓存穿透、缓存雪崩?
在 Redis 或其他缓存系统中,缓存击穿 、缓存穿透 和缓存雪崩是常见的缓存问题,它们的发生可能导致缓存系统的性能下降或数据一致性问题。下面是对这三个问题的解释及其区别:
1. 缓存击穿 (Cache Breakdown)
定义:缓存击穿指的是某些热点数据的缓存失效后,访问这些数据的请求都会穿透缓存,直接访问数据库,导致数据库压力剧增。
原因:通常是缓存中的某些数据在特定时间失效(比如:热点数据缓存过期),同时有大量的请求同时访问该数据,导致缓存未命中,所有请求都去访问数据库,造成数据库压力过大。
解决办法:
- 加锁:对于热点数据的缓存失效,可以在第一次查询时加锁,只有第一个请求去查询数据库并更新缓存,其他请求等待第一个请求完成,避免多次查询数据库。
- 使用互斥锁(分布式锁) :通过分布式锁(如 Redis 的
SETNX)来确保只有一个请求去更新缓存。
举个例子: 假设某个电商网站的首页数据是热点数据,很多用户访问时都会查询这个数据。如果缓存突然失效,所有用户的请求都会去查询数据库,这时数据库的压力就会突然增大。
2. 缓存穿透 (Cache Penetration)
定义:缓存穿透指的是请求的数据既不在缓存中,也不在数据库中,导致每次请求都需要查询数据库,绕过缓存,最终查询不到数据但仍然访问了数据库。
原因:通常是因为客户端请求了一个根本不存在的数据(如错误的 ID 或参数),这个数据即不存在于缓存中,也不存在于数据库中。每次请求都会直接穿透缓存,查询数据库。
解决办法:
- 参数校验:在业务层面,增加对请求参数的校验,避免不合法的请求进入系统。
- 空值缓存 :对于查询不到的数据,可以在缓存中存储一个空值(比如
NULL),以避免同样的请求多次穿透到数据库。通常会设置一个较短的过期时间,避免缓存被空数据占用。
举个例子 : 用户请求一个不存在的商品 ID 123456,这个商品 ID 不存在于缓存中,也不在数据库中,导致每次请求都查询数据库并返回空结果。
3. 缓存雪崩 (Cache Avalanche)
定义:缓存雪崩指的是大量缓存同时过期或失效,导致大量请求同时穿透缓存,进而访问数据库,造成数据库压力激增甚至宕机。
原因:通常是在缓存的失效时间设置不合理,导致大量缓存数据在相同时间过期,这时候大量请求直接访问数据库,造成数据库瞬时高负载,可能导致系统崩溃。
解决办法:
- 设置缓存过期时间的随机性:避免缓存数据在同一时刻过期,可以通过设置不同的过期时间来避免缓存集中失效。
- 使用延迟加载:对于一些数据,可以使用"延迟加载"策略,即当缓存失效时,不立即查询数据库,而是延迟一定时间再查询数据库,这样可以避免瞬时的流量冲击。
- 缓存预热:通过提前将热点数据加载到缓存中,避免用户访问时才发现缓存没有数据。
举个例子: 假设一个电商平台的所有商品信息缓存都在同一时刻过期,随后大量用户访问商品信息时,所有请求都穿透缓存,导致数据库瞬间承受巨大的访问压力,甚至崩溃。
总结对比
| 问题类型 | 描述 | 主要原因 | 解决方案 |
|---|---|---|---|
| 缓存击穿 | 热点数据的缓存失效,多个请求同时查询,直接访问数据库 | 热点数据缓存过期,且没有处理并发 | 使用分布式锁,保证一次查询数据库并更新缓存 |
| 缓存穿透 | 请求的数据既不在缓存中,也不在数据库中 | 查询了不存在的数据 | 参数校验,缓存空值 |
| 缓存雪崩 | 大量缓存同时过期,造成大量请求穿透缓存访问数据库 | 缓存失效时间过于集中 | 设置随机过期时间,延迟加载,缓存预热 |
了解这些问题的原因和解决办法,可以有效避免缓存系统的性能问题,提高系统的稳定性和响应能力。