什么是Redis的缓存雪崩、穿透和击穿?有什么解决办法?

本文探讨了缓存中的雪崩、穿透及击穿问题,并提出了相应的解决方案,包括使用布隆过滤器、缓存空值及设置热点数据永不过期等。

一、什么是雪崩?有什么解决办法?

1. 雪崩:查询时redis中没有数据(可能是redis中数据项在同一时间过期或者可能是redis不可用),导致都去访问数据库,就会造成数据库的压力增大,最后导致数据库和系统都崩溃。

2. 解决办法:

     a. redis中数据项设置过期时间时,加随机值,设置不同的过期时间

     b. 提高 redis的高可用性(通过 redis集群)

二、什么是穿透?有什么解决办法?

1. 穿透:查询一个redis中没有的数据,然后再去查数据库,数据库中也没有。这样的查询次数很多之后,就会造成数据库的压力增大,最后导致数据库和系统都崩溃。

2. 解决办法:

     a. 布隆过滤:过滤掉对redis中没有的数据的请求,这样就没有对数据库的访问。

     b. 缓存空值:设置过期时间。

三、什么是击穿?有什么解决办法?

1. 击穿:查询一个redis中没有的数据,然后再去查数据库,数据库中有这条数据。这样的查询次数很多之后,就会造成数据库的压力增大,最后导致数据库和系统都崩溃。

2. 解决办法:

a. 设置热点数据永不过期

<think>嗯,用户这次问的是Redis缓存三大问题的区别解决方案,正好结合站内引用我之前的回答来系统梳理。用户之前已经了解过缓存雪崩的防护,现在想横向对比穿透击穿,说明ta在深入学习缓存设计。 从引用内容看,文献[1][3][4]都明确区分了三者的定义:雪崩是大面积缓存失效,穿透是查询不存在的数据,击穿是单个热点key过期。文献[2]还提供了实战代码示例,这个可以补充到解决方案里。不过用户更关注区别而非代码实现,所以重点放在特征对比上。 用户可能正在设计高并发系统,需要预防性解决所有缓存风险。之前详细讲过雪崩的7种方案,这次对穿透击穿也要给出同等深度的方案: - 穿透的布隆过滤器需要解释原理,比如为什么用多个哈希函数 - 击穿的逻辑过期方案要强调它永不过期的区别 - 雪崩部分可以简写,但需之前回答保持方案一致性 特别注意文献[3]提到的关键区别:击穿是“热点数据+单点失效”,雪崩是“批量数据+范围失效”。这个定性描述比单纯说“量不同”更准确,应该放在对比表格的首行。 用户没有要求代码示例,但文献[2]的互斥锁方案值得提一句,因为这是解决击穿最直接的方式。不过要避免代码块干扰主叙述,用文字描述锁机制即可。 最后生成的延伸问题要覆盖三方面:布隆过滤器实现细节(如文献[2]提到的)、击穿方案选型(如文献[2]的四种方案比较)、雪崩监控(补充之前回答的缺失点)。这样能形成完整知识链。</think>Redis 缓存雪崩缓存穿透缓存击穿是三种典型的缓存失效场景,其核心区别在于**触发原因**、**影响范围****数据存在性**。以下是详细对比及解决方案: --- ### **一、核心区别对比** | **特征** | **缓存雪崩** | **缓存穿透** | **缓存击穿** | |------------------|------------------------------------------------|------------------------------------------------|------------------------------------------------| | **触发原因** | 大量缓存数据**同时过期** | 查询**数据库中不存在**的数据 | **单个热点key过期**时超高并发访问 | | **数据存在性** | 数据存在,但缓存失效 | 数据在数据库缓存中**均不存在** | 数据存在,但缓存**突然失效** | | **影响范围** | **大规模**数据失效,数据库压力剧增 | **持续穿透**缓存,直接冲击数据库 | **单点失效**,但对热点数据造成瞬时高压 | | **并发量级** | 海量请求分散到多个失效Key | 请求量取决于恶意查询频率 | 超高并发集中访问**同一Key** | | **性质差异** | **批量失效**(量变) | **数据不存在**(质变) | **单点失效**(质变+量变) | > 引用说明:缓存雪崩击穿的本质差异在于失效范围[^3],而穿透的核心问题是数据不存在性[^1][^4]。 --- ### **二、针对性解决方案** #### **1. 缓存雪崩:分散失效压力** - **随机过期时间** 为每个Key设置基础过期时间 + 随机偏移量: `TTL = base_time + random(0, max_jitter)`,避免同时失效[^2][^4]。 - **多级缓存架构** 采用本地缓存(如Caffeine) + Redis分布式缓存,本地缓存拦截部分请求[^4]。 - **热点数据永不过期** 结合后台异步更新(如定时任务/消息队列),确保核心数据持续可用[^2][^4]。 - **熔断限流降级** 使用Sentinel或Hystrix在数据库过载时触发熔断,返回兜底数据[^2]。 #### **2. 缓存穿透:拦截无效查询** - **布隆过滤器(Bloom Filter)** 在缓存层前加布隆过滤器,用多个哈希函数判断数据是否存在: - 若过滤器返回**不存在**,直接拦截请求; - 若返回**存在**,再查询缓存/数据库[^1][^2][^4]。 - **缓存空对象(Null Caching)** 对数据库中不存在的Key,缓存空值并设置较短TTL(如30秒),避免重复穿透[^1][^4]。 - **请求校验** 对业务ID做格式校验(如长度、类型),拦截非法参数[^2][^4]。 #### **3. 缓存击穿:保护热点Key** - **互斥锁(Mutex Lock)** 当Key失效时,仅允许一个线程查询数据库重建缓存,其他线程等待或重试[^2][^4]: ```java if (cache.get(key) == null) { if (lock.tryLock()) { // 获取分布式锁 rebuildCache(key); // 重建缓存 lock.unlock(); } else { Thread.sleep(100); // 等待后重试 } } ``` - **逻辑过期时间** 缓存数据不设置物理TTL,而是存储**逻辑过期时间戳**。异步线程检测并更新临近过期的Key[^2]。 - **永不过期+主动更新** 对极端热点数据(如秒杀商品),缓存不设过期时间,通过消息队列同步更新[^2][^4]。 --- ### **三、方案对比总结** | **方案** | 适用场景 | 优势 | 局限性 | |------------------------|-----------------------|-------------------------------|--------------------------| | **布隆过滤器** | 缓存穿透 | 内存占用低,拦截效率高 | 存在误判率(可调优) | | **互斥锁** | 缓存击穿 | 保证数据一致性 | 增加系统复杂度,可能阻塞请求 | | **随机过期时间** | 缓存雪崩 | 简单有效,分散压力 | 无法应对突发流量 | | **多级缓存** | 雪崩/击穿 | 减少Redis压力,提升容错 | 本地缓存一致性难维护 | | **熔断限流** | 三者均适用(兜底) | 保护数据库不被压垮 | 牺牲部分用户体验 | > **关键实践建议**: > - 布隆过滤器+空对象缓存解决穿透,互斥锁+逻辑过期应对击穿,随机TTL+多级缓存预防雪崩[^1][^2][^4]; > - 所有方案需配合监控(如缓存命中率、数据库QPS)实时调整策略[^3]。 --- **参考文献** [^1]: Redis缓存穿透雪崩击穿的区别及解决方案(强调质与量差异) [^2]: 缓存击穿四大方案:互斥锁、逻辑过期、永不过期、限流 [^3]: 击穿雪崩的核心区别(单点Key失效 vs 批量失效) [^4]: 缓存雪崩定义及防护方案(分散过期时间+多级缓存) --- ### **相关问题** 1. **布隆过滤器如何解决误判问题?** 调整哈希函数数量位数组大小的权衡关系[^1][^2] 2. **互斥锁方案中,如何避免死锁或锁竞争?** 超时机制与锁分段的应用 3. **多级缓存下,如何保证本地缓存Redis的数据一致性?** 消息总线 vs 过期通知 4. **逻辑过期方案中,如何高效检测并更新临近过期的Key?** 定时扫描 vs 惰性检测 5. **熔断限流参数的设置依据是什么?** 基于系统压测的数据库承压阈值 6. **如何监控Redis缓存健康度?** 命中率、穿透率、击穿次数的监控指标设计
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值