欢迎光临
我们一直在努力

缓存雪崩、缓存穿透、缓存击穿:高并发下的缓存稳定性深度解析

文章目录

  • 前言
  • 一、三大缓存问题的核心区别
  • 二、缓存穿透
    • 2.1 什么是缓存穿透?
    • 2.2 缓存穿透的业务流程图
    • 2.3 典型场景
    • 2.4 危害分析
    • 2.5 解决方案
      • 方案一:布隆过滤器
      • 方案二:缓存空对象
      • 方案三:两种方案结合
  • 三、缓存击穿
    • 3.1 什么是缓存击穿?
    • 3.2 缓存击穿问题示意图
    • 3.3 典型场景
    • 3.4 危害分析
    • 3.5 解决方案
      • 方案一:互斥锁
      • 方案二:逻辑过期
      • 方案三:热点Key永不过期
  • 四、缓存雪崩
    • 4.1 什么是缓存雪崩?
    • 4.2 缓存雪崩问题示意图
    • 4.3 触发场景
      • 场景一:大量Key同时过期
      • 场景二:Redis集群故障
    • 4.4 危害分析
    • 4.5 解决方案
      • 方案一:过期时间随机化
      • 方案二:多级缓存
      • 方案三:Redis高可用架构
      • 方案四:限流降级
  • 五、三种问题的对比总结
  • 六、生产环境最佳实践
    • 6.1 分层防御策略
    • 6.2 监控与告警
    • 6.3 压测与演练
  • 七、总结

前言

在高并发系统设计中,缓存是抵挡数据库洪峰的第一道防线。然而,这道防线并非固若金汤——缓存雪崩、缓存穿透、缓存击穿作为三大经典缓存问题,几乎是每一位后端工程师在实际生产中都可能遇到的"梦魇"。它们名字相似,但成因、表现和解决方案却截然不同。


一、三大缓存问题的核心区别

在深入细节之前,我们先通过一张对比表格快速建立整体认知:

问题问题本质发生场景核心影响关键特征
缓存穿透 数据不存在 查询根本不存在的数据 绕过缓存直击DB 缓存和DB都没有
缓存击穿 热点Key过期 某个热点Key刚好过期 瞬间大并发打崩DB 单个Key过期,并发极高
缓存雪崩 大规模失效 大量Key同时过期或Redis宕机 整体流量冲击DB 批量Key失效,范围大

二、缓存穿透

2.1 什么是缓存穿透?

缓存穿透是指查询一个根本不存在的数据。由于缓存中不存在,请求会直接穿透到数据库;又因为数据库中也不存在,所以无法回写缓存。这就导致每次请求这种不存在的数据时,都会直击数据库。

2.2 缓存穿透的业务流程图

下面这张图清晰地展示了缓存穿透的发生机制——当请求的数据在缓存和数据库中都不存在时,每次请求都会直接访问数据库,缓存形同虚设。

#mermaid-svg-zrvjp5Lb5r74UtOB{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-zrvjp5Lb5r74UtOB .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-zrvjp5Lb5r74UtOB .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-zrvjp5Lb5r74UtOB .error-icon{fill:#552222;}#mermaid-svg-zrvjp5Lb5r74UtOB .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-zrvjp5Lb5r74UtOB .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-zrvjp5Lb5r74UtOB .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-zrvjp5Lb5r74UtOB .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-zrvjp5Lb5r74UtOB .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-zrvjp5Lb5r74UtOB .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-zrvjp5Lb5r74UtOB .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-zrvjp5Lb5r74UtOB .marker{fill:#333333;stroke:#333333;}#mermaid-svg-zrvjp5Lb5r74UtOB .marker.cross{stroke:#333333;}#mermaid-svg-zrvjp5Lb5r74UtOB svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-zrvjp5Lb5r74UtOB p{margin:0;}#mermaid-svg-zrvjp5Lb5r74UtOB .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-zrvjp5Lb5r74UtOB .cluster-label text{fill:#333;}#mermaid-svg-zrvjp5Lb5r74UtOB .cluster-label span{color:#333;}#mermaid-svg-zrvjp5Lb5r74UtOB .cluster-label span p{background-color:transparent;}#mermaid-svg-zrvjp5Lb5r74UtOB .label text,#mermaid-svg-zrvjp5Lb5r74UtOB span{fill:#333;color:#333;}#mermaid-svg-zrvjp5Lb5r74UtOB .node rect,#mermaid-svg-zrvjp5Lb5r74UtOB .node circle,#mermaid-svg-zrvjp5Lb5r74UtOB .node ellipse,#mermaid-svg-zrvjp5Lb5r74UtOB .node polygon,#mermaid-svg-zrvjp5Lb5r74UtOB .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-zrvjp5Lb5r74UtOB .rough-node .label text,#mermaid-svg-zrvjp5Lb5r74UtOB .node .label text,#mermaid-svg-zrvjp5Lb5r74UtOB .image-shape .label,#mermaid-svg-zrvjp5Lb5r74UtOB .icon-shape .label{text-anchor:middle;}#mermaid-svg-zrvjp5Lb5r74UtOB .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-zrvjp5Lb5r74UtOB .rough-node .label,#mermaid-svg-zrvjp5Lb5r74UtOB .node .label,#mermaid-svg-zrvjp5Lb5r74UtOB .image-shape .label,#mermaid-svg-zrvjp5Lb5r74UtOB .icon-shape .label{text-align:center;}#mermaid-svg-zrvjp5Lb5r74UtOB .node.clickable{cursor:pointer;}#mermaid-svg-zrvjp5Lb5r74UtOB .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-zrvjp5Lb5r74UtOB .arrowheadPath{fill:#333333;}#mermaid-svg-zrvjp5Lb5r74UtOB .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-zrvjp5Lb5r74UtOB .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-zrvjp5Lb5r74UtOB .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-zrvjp5Lb5r74UtOB .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-zrvjp5Lb5r74UtOB .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-zrvjp5Lb5r74UtOB .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-zrvjp5Lb5r74UtOB .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-zrvjp5Lb5r74UtOB .cluster text{fill:#333;}#mermaid-svg-zrvjp5Lb5r74UtOB .cluster span{color:#333;}#mermaid-svg-zrvjp5Lb5r74UtOB div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-zrvjp5Lb5r74UtOB .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-zrvjp5Lb5r74UtOB rect.text{fill:none;stroke-width:0;}#mermaid-svg-zrvjp5Lb5r74UtOB .icon-shape,#mermaid-svg-zrvjp5Lb5r74UtOB .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-zrvjp5Lb5r74UtOB .icon-shape p,#mermaid-svg-zrvjp5Lb5r74UtOB .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-zrvjp5Lb5r74UtOB .icon-shape rect,#mermaid-svg-zrvjp5Lb5r74UtOB .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-zrvjp5Lb5r74UtOB .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-zrvjp5Lb5r74UtOB .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-zrvjp5Lb5r74UtOB :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

命中

未命中

存在

不存在

用户请求

查询缓存

返回数据

查询数据库

数据是否存在

返回数据

返回空值

2.3 典型场景

  • 恶意攻击:攻击者频繁请求不存在的ID(如-1、9999999等)
  • 业务误操作:前端传入不存在的查询条件
  • 数据未初始化:新业务上线,历史数据尚未生成

2.4 危害分析

当这种请求量足够大时,数据库会承受大量无效查询,导致:

  • 数据库连接数耗尽
  • CPU飙升
  • 正常业务请求被阻塞
  • 严重时引发数据库宕机

2.5 解决方案

方案一:布隆过滤器

原理:使用一个超大的位数组和多个哈希函数,将数据库中所有存在的key映射到位数组中。请求到达时,先通过布隆过滤器判断key是否存在:

  • 如果过滤器说不存在,则一定不存在,直接返回
  • 如果过滤器说存在,则可能存在(有误判率),继续查询缓存和数据库

布隆过滤器拦截流程:

#mermaid-svg-R1KuF5tGYUtIXRI0{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-R1KuF5tGYUtIXRI0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-R1KuF5tGYUtIXRI0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-R1KuF5tGYUtIXRI0 .error-icon{fill:#552222;}#mermaid-svg-R1KuF5tGYUtIXRI0 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-R1KuF5tGYUtIXRI0 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-R1KuF5tGYUtIXRI0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-R1KuF5tGYUtIXRI0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-R1KuF5tGYUtIXRI0 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-R1KuF5tGYUtIXRI0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-R1KuF5tGYUtIXRI0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-R1KuF5tGYUtIXRI0 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-R1KuF5tGYUtIXRI0 .marker.cross{stroke:#333333;}#mermaid-svg-R1KuF5tGYUtIXRI0 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-R1KuF5tGYUtIXRI0 p{margin:0;}#mermaid-svg-R1KuF5tGYUtIXRI0 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-R1KuF5tGYUtIXRI0 .cluster-label text{fill:#333;}#mermaid-svg-R1KuF5tGYUtIXRI0 .cluster-label span{color:#333;}#mermaid-svg-R1KuF5tGYUtIXRI0 .cluster-label span p{background-color:transparent;}#mermaid-svg-R1KuF5tGYUtIXRI0 .label text,#mermaid-svg-R1KuF5tGYUtIXRI0 span{fill:#333;color:#333;}#mermaid-svg-R1KuF5tGYUtIXRI0 .node rect,#mermaid-svg-R1KuF5tGYUtIXRI0 .node circle,#mermaid-svg-R1KuF5tGYUtIXRI0 .node ellipse,#mermaid-svg-R1KuF5tGYUtIXRI0 .node polygon,#mermaid-svg-R1KuF5tGYUtIXRI0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-R1KuF5tGYUtIXRI0 .rough-node .label text,#mermaid-svg-R1KuF5tGYUtIXRI0 .node .label text,#mermaid-svg-R1KuF5tGYUtIXRI0 .image-shape .label,#mermaid-svg-R1KuF5tGYUtIXRI0 .icon-shape .label{text-anchor:middle;}#mermaid-svg-R1KuF5tGYUtIXRI0 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-R1KuF5tGYUtIXRI0 .rough-node .label,#mermaid-svg-R1KuF5tGYUtIXRI0 .node .label,#mermaid-svg-R1KuF5tGYUtIXRI0 .image-shape .label,#mermaid-svg-R1KuF5tGYUtIXRI0 .icon-shape .label{text-align:center;}#mermaid-svg-R1KuF5tGYUtIXRI0 .node.clickable{cursor:pointer;}#mermaid-svg-R1KuF5tGYUtIXRI0 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-R1KuF5tGYUtIXRI0 .arrowheadPath{fill:#333333;}#mermaid-svg-R1KuF5tGYUtIXRI0 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-R1KuF5tGYUtIXRI0 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-R1KuF5tGYUtIXRI0 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-R1KuF5tGYUtIXRI0 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-R1KuF5tGYUtIXRI0 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-R1KuF5tGYUtIXRI0 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-R1KuF5tGYUtIXRI0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-R1KuF5tGYUtIXRI0 .cluster text{fill:#333;}#mermaid-svg-R1KuF5tGYUtIXRI0 .cluster span{color:#333;}#mermaid-svg-R1KuF5tGYUtIXRI0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-R1KuF5tGYUtIXRI0 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-R1KuF5tGYUtIXRI0 rect.text{fill:none;stroke-width:0;}#mermaid-svg-R1KuF5tGYUtIXRI0 .icon-shape,#mermaid-svg-R1KuF5tGYUtIXRI0 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-R1KuF5tGYUtIXRI0 .icon-shape p,#mermaid-svg-R1KuF5tGYUtIXRI0 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-R1KuF5tGYUtIXRI0 .icon-shape rect,#mermaid-svg-R1KuF5tGYUtIXRI0 .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-R1KuF5tGYUtIXRI0 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-R1KuF5tGYUtIXRI0 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-R1KuF5tGYUtIXRI0 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

不存在

存在

命中

未命中

用户请求

布隆过滤器

直接返回

查询缓存

返回数据

查询数据库

返回结果

核心优势:

  • 内存占用极小:1000万数据仅需约12MB
  • 性能极高:时间复杂度O(k),k为哈希函数个数

局限性:

  • 存在误判率(可通过参数控制在1%以内)
  • 不支持删除操作(可考虑计数布隆过滤器)
  • 需要提前加载所有存在的key

方案二:缓存空对象

原理:当查询数据库发现不存在时,仍然将这个"空结果"写入缓存,但设置较短的过期时间(如30-60秒)。

核心优势:

  • 实现简单,逻辑直观
  • 适用于数据变化不频繁的场景

局限性:

  • 会占用额外的缓存空间(可通过短过期时间缓解)
  • 可能导致短暂的数据不一致

方案三:两种方案结合

在实际生产中,通常采用布隆过滤器 + 缓存空对象双重保障:

  • 布隆过滤器:高效拦截恶意攻击和遍历请求
  • 缓存空对象:兜底处理偶发性不存在的数据

三、缓存击穿

3.1 什么是缓存击穿?

缓存击穿是指一个热点key在某个时间点恰好过期,而此时有大量并发请求访问这个key。由于缓存失效,这些请求会同时穿透到数据库,瞬间给数据库带来巨大压力。

3.2 缓存击穿问题示意图

#mermaid-svg-32UdUCcPaM0ClIMQ{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-32UdUCcPaM0ClIMQ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-32UdUCcPaM0ClIMQ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-32UdUCcPaM0ClIMQ .error-icon{fill:#552222;}#mermaid-svg-32UdUCcPaM0ClIMQ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-32UdUCcPaM0ClIMQ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-32UdUCcPaM0ClIMQ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-32UdUCcPaM0ClIMQ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-32UdUCcPaM0ClIMQ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-32UdUCcPaM0ClIMQ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-32UdUCcPaM0ClIMQ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-32UdUCcPaM0ClIMQ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-32UdUCcPaM0ClIMQ .marker.cross{stroke:#333333;}#mermaid-svg-32UdUCcPaM0ClIMQ svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-32UdUCcPaM0ClIMQ p{margin:0;}#mermaid-svg-32UdUCcPaM0ClIMQ .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-32UdUCcPaM0ClIMQ .cluster-label text{fill:#333;}#mermaid-svg-32UdUCcPaM0ClIMQ .cluster-label span{color:#333;}#mermaid-svg-32UdUCcPaM0ClIMQ .cluster-label span p{background-color:transparent;}#mermaid-svg-32UdUCcPaM0ClIMQ .label text,#mermaid-svg-32UdUCcPaM0ClIMQ span{fill:#333;color:#333;}#mermaid-svg-32UdUCcPaM0ClIMQ .node rect,#mermaid-svg-32UdUCcPaM0ClIMQ .node circle,#mermaid-svg-32UdUCcPaM0ClIMQ .node ellipse,#mermaid-svg-32UdUCcPaM0ClIMQ .node polygon,#mermaid-svg-32UdUCcPaM0ClIMQ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-32UdUCcPaM0ClIMQ .rough-node .label text,#mermaid-svg-32UdUCcPaM0ClIMQ .node .label text,#mermaid-svg-32UdUCcPaM0ClIMQ .image-shape .label,#mermaid-svg-32UdUCcPaM0ClIMQ .icon-shape .label{text-anchor:middle;}#mermaid-svg-32UdUCcPaM0ClIMQ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-32UdUCcPaM0ClIMQ .rough-node .label,#mermaid-svg-32UdUCcPaM0ClIMQ .node .label,#mermaid-svg-32UdUCcPaM0ClIMQ .image-shape .label,#mermaid-svg-32UdUCcPaM0ClIMQ .icon-shape .label{text-align:center;}#mermaid-svg-32UdUCcPaM0ClIMQ .node.clickable{cursor:pointer;}#mermaid-svg-32UdUCcPaM0ClIMQ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-32UdUCcPaM0ClIMQ .arrowheadPath{fill:#333333;}#mermaid-svg-32UdUCcPaM0ClIMQ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-32UdUCcPaM0ClIMQ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-32UdUCcPaM0ClIMQ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-32UdUCcPaM0ClIMQ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-32UdUCcPaM0ClIMQ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-32UdUCcPaM0ClIMQ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-32UdUCcPaM0ClIMQ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-32UdUCcPaM0ClIMQ .cluster text{fill:#333;}#mermaid-svg-32UdUCcPaM0ClIMQ .cluster span{color:#333;}#mermaid-svg-32UdUCcPaM0ClIMQ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-32UdUCcPaM0ClIMQ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-32UdUCcPaM0ClIMQ rect.text{fill:none;stroke-width:0;}#mermaid-svg-32UdUCcPaM0ClIMQ .icon-shape,#mermaid-svg-32UdUCcPaM0ClIMQ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-32UdUCcPaM0ClIMQ .icon-shape p,#mermaid-svg-32UdUCcPaM0ClIMQ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-32UdUCcPaM0ClIMQ .icon-shape rect,#mermaid-svg-32UdUCcPaM0ClIMQ .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-32UdUCcPaM0ClIMQ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-32UdUCcPaM0ClIMQ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-32UdUCcPaM0ClIMQ :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

击穿瞬间

未命中

未命中

未命中

未命中

未命中

时间点t0

热点Key刚好过期

请求1

请求2

请求3

请求4

请求N…

查询缓存

查询缓存

查询缓存

查询缓存

查询缓存

数据库

数据库瞬间压力暴增连接耗尽、响应超时

正常情况

热点Key存在

请求1命中缓存

请求2命中缓存

请求3命中缓存

返回数据

3.3 典型场景

  • 首页Banner:首页轮播图配置在凌晨0点过期,零点后大量用户访问
  • 热门商品:秒杀商品详情页,商品信息缓存过期
  • 微博热搜:某个热搜话题突然爆火,对应缓存恰好过期

3.4 危害分析

击穿的特点是"单点高并发"——针对的是单个Key,但这个Key是热点,并发量极高。如果处理不当,可能导致:

  • 数据库瞬间QPS飙升
  • 连接池被打满
  • 响应时间急剧上升
  • 服务不可用

3.5 解决方案

方案一:互斥锁

原理:当缓存失效时,不是所有请求都去查询数据库,而是只让一个请求去查询并重建缓存,其他请求等待或重试。

互斥锁解决方案流程图

#mermaid-svg-odwrwVHfHRvcv5hV{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-odwrwVHfHRvcv5hV .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-odwrwVHfHRvcv5hV .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-odwrwVHfHRvcv5hV .error-icon{fill:#552222;}#mermaid-svg-odwrwVHfHRvcv5hV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-odwrwVHfHRvcv5hV .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-odwrwVHfHRvcv5hV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-odwrwVHfHRvcv5hV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-odwrwVHfHRvcv5hV .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-odwrwVHfHRvcv5hV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-odwrwVHfHRvcv5hV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-odwrwVHfHRvcv5hV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-odwrwVHfHRvcv5hV .marker.cross{stroke:#333333;}#mermaid-svg-odwrwVHfHRvcv5hV svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-odwrwVHfHRvcv5hV p{margin:0;}#mermaid-svg-odwrwVHfHRvcv5hV .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-odwrwVHfHRvcv5hV .cluster-label text{fill:#333;}#mermaid-svg-odwrwVHfHRvcv5hV .cluster-label span{color:#333;}#mermaid-svg-odwrwVHfHRvcv5hV .cluster-label span p{background-color:transparent;}#mermaid-svg-odwrwVHfHRvcv5hV .label text,#mermaid-svg-odwrwVHfHRvcv5hV span{fill:#333;color:#333;}#mermaid-svg-odwrwVHfHRvcv5hV .node rect,#mermaid-svg-odwrwVHfHRvcv5hV .node circle,#mermaid-svg-odwrwVHfHRvcv5hV .node ellipse,#mermaid-svg-odwrwVHfHRvcv5hV .node polygon,#mermaid-svg-odwrwVHfHRvcv5hV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-odwrwVHfHRvcv5hV .rough-node .label text,#mermaid-svg-odwrwVHfHRvcv5hV .node .label text,#mermaid-svg-odwrwVHfHRvcv5hV .image-shape .label,#mermaid-svg-odwrwVHfHRvcv5hV .icon-shape .label{text-anchor:middle;}#mermaid-svg-odwrwVHfHRvcv5hV .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-odwrwVHfHRvcv5hV .rough-node .label,#mermaid-svg-odwrwVHfHRvcv5hV .node .label,#mermaid-svg-odwrwVHfHRvcv5hV .image-shape .label,#mermaid-svg-odwrwVHfHRvcv5hV .icon-shape .label{text-align:center;}#mermaid-svg-odwrwVHfHRvcv5hV .node.clickable{cursor:pointer;}#mermaid-svg-odwrwVHfHRvcv5hV .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-odwrwVHfHRvcv5hV .arrowheadPath{fill:#333333;}#mermaid-svg-odwrwVHfHRvcv5hV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-odwrwVHfHRvcv5hV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-odwrwVHfHRvcv5hV .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-odwrwVHfHRvcv5hV .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-odwrwVHfHRvcv5hV .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-odwrwVHfHRvcv5hV .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-odwrwVHfHRvcv5hV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-odwrwVHfHRvcv5hV .cluster text{fill:#333;}#mermaid-svg-odwrwVHfHRvcv5hV .cluster span{color:#333;}#mermaid-svg-odwrwVHfHRvcv5hV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-odwrwVHfHRvcv5hV .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-odwrwVHfHRvcv5hV rect.text{fill:none;stroke-width:0;}#mermaid-svg-odwrwVHfHRvcv5hV .icon-shape,#mermaid-svg-odwrwVHfHRvcv5hV .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-odwrwVHfHRvcv5hV .icon-shape p,#mermaid-svg-odwrwVHfHRvcv5hV .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-odwrwVHfHRvcv5hV .icon-shape rect,#mermaid-svg-odwrwVHfHRvcv5hV .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-odwrwVHfHRvcv5hV .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-odwrwVHfHRvcv5hV .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-odwrwVHfHRvcv5hV :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

命中

未命中

成功

失败

用户请求

查询缓存

返回数据

尝试获取锁

查询数据库

重建缓存

释放锁

返回数据

等待后重试

核心流程:

  • 请求发现缓存不存在
  • 尝试获取分布式锁
  • 获取锁成功的请求查询数据库并重建缓存
  • 获取锁失败的请求等待后重试
  • 重建完成后释放锁
  • 核心优势:

    • 保证只有一个请求查询数据库
    • 实现相对简单

    局限性:

    • 引入锁竞争,降低系统吞吐量
    • 需设置合理锁超时,避免死锁
    • 可能造成线程阻塞

    方案二:逻辑过期

    原理:缓存中不设置物理过期时间,而是存储一个"逻辑过期时间"。当查询发现逻辑过期时,启动一个独立线程去更新缓存,当前请求返回旧数据。

    核心流程:

  • 缓存数据包含:真实数据 + 逻辑过期时间戳
  • 查询时判断逻辑是否过期
  • 未过期:直接返回数据
  • 已过期:尝试获取分布式锁
  • 获取锁成功:异步线程更新缓存
  • 无论是否获取锁,都返回旧数据
  • 核心优势:

    • 读操作无阻塞,性能极高
    • 适合"最终一致性"可接受的场景

    局限性:

    • 实现复杂度较高
    • 数据短暂不一致(旧数据可能被返回)

    方案三:热点Key永不过期

    原理:对于明确的热点Key,不设置物理过期时间,而是通过后台定时任务主动更新。

    适用场景:业务可预知的热点(如首页配置、爆款商品)

    核心优势:

    • 彻底消除击穿风险
    • 实现简单

    局限性:

    • 只能用于可预知的热点
    • 需要额外的定时任务维护

    四、缓存雪崩

    4.1 什么是缓存雪崩?

    缓存雪崩是指由于大量缓存key同时过期或Redis节点宕机,导致所有请求直接落到数据库上,数据库瞬间压力过大甚至崩溃的现象。

    4.2 缓存雪崩问题示意图

    #mermaid-svg-YbRUji9zX655m49F{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-YbRUji9zX655m49F .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-YbRUji9zX655m49F .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-YbRUji9zX655m49F .error-icon{fill:#552222;}#mermaid-svg-YbRUji9zX655m49F .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-YbRUji9zX655m49F .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-YbRUji9zX655m49F .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-YbRUji9zX655m49F .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-YbRUji9zX655m49F .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-YbRUji9zX655m49F .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-YbRUji9zX655m49F .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-YbRUji9zX655m49F .marker{fill:#333333;stroke:#333333;}#mermaid-svg-YbRUji9zX655m49F .marker.cross{stroke:#333333;}#mermaid-svg-YbRUji9zX655m49F svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-YbRUji9zX655m49F p{margin:0;}#mermaid-svg-YbRUji9zX655m49F .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-YbRUji9zX655m49F .cluster-label text{fill:#333;}#mermaid-svg-YbRUji9zX655m49F .cluster-label span{color:#333;}#mermaid-svg-YbRUji9zX655m49F .cluster-label span p{background-color:transparent;}#mermaid-svg-YbRUji9zX655m49F .label text,#mermaid-svg-YbRUji9zX655m49F span{fill:#333;color:#333;}#mermaid-svg-YbRUji9zX655m49F .node rect,#mermaid-svg-YbRUji9zX655m49F .node circle,#mermaid-svg-YbRUji9zX655m49F .node ellipse,#mermaid-svg-YbRUji9zX655m49F .node polygon,#mermaid-svg-YbRUji9zX655m49F .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-YbRUji9zX655m49F .rough-node .label text,#mermaid-svg-YbRUji9zX655m49F .node .label text,#mermaid-svg-YbRUji9zX655m49F .image-shape .label,#mermaid-svg-YbRUji9zX655m49F .icon-shape .label{text-anchor:middle;}#mermaid-svg-YbRUji9zX655m49F .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-YbRUji9zX655m49F .rough-node .label,#mermaid-svg-YbRUji9zX655m49F .node .label,#mermaid-svg-YbRUji9zX655m49F .image-shape .label,#mermaid-svg-YbRUji9zX655m49F .icon-shape .label{text-align:center;}#mermaid-svg-YbRUji9zX655m49F .node.clickable{cursor:pointer;}#mermaid-svg-YbRUji9zX655m49F .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-YbRUji9zX655m49F .arrowheadPath{fill:#333333;}#mermaid-svg-YbRUji9zX655m49F .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-YbRUji9zX655m49F .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-YbRUji9zX655m49F .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YbRUji9zX655m49F .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-YbRUji9zX655m49F .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YbRUji9zX655m49F .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-YbRUji9zX655m49F .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-YbRUji9zX655m49F .cluster text{fill:#333;}#mermaid-svg-YbRUji9zX655m49F .cluster span{color:#333;}#mermaid-svg-YbRUji9zX655m49F div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-YbRUji9zX655m49F .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-YbRUji9zX655m49F rect.text{fill:none;stroke-width:0;}#mermaid-svg-YbRUji9zX655m49F .icon-shape,#mermaid-svg-YbRUji9zX655m49F .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YbRUji9zX655m49F .icon-shape p,#mermaid-svg-YbRUji9zX655m49F .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-YbRUji9zX655m49F .icon-shape rect,#mermaid-svg-YbRUji9zX655m49F .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YbRUji9zX655m49F .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-YbRUji9zX655m49F .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-YbRUji9zX655m49F :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    雪崩场景二:Redis集群故障

    主节点宕机

    网络分区

    整体故障

    Redis集群

    哨兵切换服务短暂不可用

    部分节点不可用

    Redis完全不可用

    所有请求

    数据库

    数据库直接被击穿

    雪崩场景一:大量Key同时过期

    时间到达12:00

    Key1过期

    Key2过期

    Key3过期

    请求组A

    请求组B

    请求组C

    缓存失效

    缓存失效

    缓存失效

    数据库

    数据库瞬间承受数倍于平时的流量

    正常缓存分布

    Key1 过期时间: 12:00

    Key2 过期时间: 12:00

    Key3 过期时间: 12:00

    Key4 过期时间: 12:05

    Key5 过期时间: 12:10

    4.3 触发场景

    场景一:大量Key同时过期

    • 业务初始化时设置了相同的过期时间(如统一凌晨0点过期)
    • 定时任务批量更新缓存,导致同一时间点大量失效

    场景二:Redis集群故障

    • 主节点宕机,哨兵正在切换
    • 网络分区导致部分节点不可用
    • 集群整体故障

    4.4 危害分析

    雪崩是三个问题中影响范围最大的:

    • 数据库可能承受平时10倍甚至100倍的流量
    • 服务响应时间急剧上升
    • 可能引发服务链式崩溃

    4.5 解决方案

    方案一:过期时间随机化

    原理:在设置缓存过期时间时,在基础时间上增加一个随机偏移量,避免大量Key同时过期。

    实践方法:

    • 基础过期时间设为1小时
    • 随机增加0-10分钟的偏移
    • 使Key的过期时间均匀分布

    核心优势:

    • 实现最简单,效果显著
    • 几乎零成本

    方案二:多级缓存

    原理:构建多级缓存体系,当一级缓存失效时,二级缓存仍能提供服务。

    多级缓存架构图:

    #mermaid-svg-CFHLw9rtyZWuJQfM{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-CFHLw9rtyZWuJQfM .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-CFHLw9rtyZWuJQfM .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-CFHLw9rtyZWuJQfM .error-icon{fill:#552222;}#mermaid-svg-CFHLw9rtyZWuJQfM .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CFHLw9rtyZWuJQfM .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-CFHLw9rtyZWuJQfM .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CFHLw9rtyZWuJQfM .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CFHLw9rtyZWuJQfM .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-CFHLw9rtyZWuJQfM .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CFHLw9rtyZWuJQfM .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CFHLw9rtyZWuJQfM .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CFHLw9rtyZWuJQfM .marker.cross{stroke:#333333;}#mermaid-svg-CFHLw9rtyZWuJQfM svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CFHLw9rtyZWuJQfM p{margin:0;}#mermaid-svg-CFHLw9rtyZWuJQfM .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-CFHLw9rtyZWuJQfM .cluster-label text{fill:#333;}#mermaid-svg-CFHLw9rtyZWuJQfM .cluster-label span{color:#333;}#mermaid-svg-CFHLw9rtyZWuJQfM .cluster-label span p{background-color:transparent;}#mermaid-svg-CFHLw9rtyZWuJQfM .label text,#mermaid-svg-CFHLw9rtyZWuJQfM span{fill:#333;color:#333;}#mermaid-svg-CFHLw9rtyZWuJQfM .node rect,#mermaid-svg-CFHLw9rtyZWuJQfM .node circle,#mermaid-svg-CFHLw9rtyZWuJQfM .node ellipse,#mermaid-svg-CFHLw9rtyZWuJQfM .node polygon,#mermaid-svg-CFHLw9rtyZWuJQfM .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CFHLw9rtyZWuJQfM .rough-node .label text,#mermaid-svg-CFHLw9rtyZWuJQfM .node .label text,#mermaid-svg-CFHLw9rtyZWuJQfM .image-shape .label,#mermaid-svg-CFHLw9rtyZWuJQfM .icon-shape .label{text-anchor:middle;}#mermaid-svg-CFHLw9rtyZWuJQfM .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-CFHLw9rtyZWuJQfM .rough-node .label,#mermaid-svg-CFHLw9rtyZWuJQfM .node .label,#mermaid-svg-CFHLw9rtyZWuJQfM .image-shape .label,#mermaid-svg-CFHLw9rtyZWuJQfM .icon-shape .label{text-align:center;}#mermaid-svg-CFHLw9rtyZWuJQfM .node.clickable{cursor:pointer;}#mermaid-svg-CFHLw9rtyZWuJQfM .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-CFHLw9rtyZWuJQfM .arrowheadPath{fill:#333333;}#mermaid-svg-CFHLw9rtyZWuJQfM .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-CFHLw9rtyZWuJQfM .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-CFHLw9rtyZWuJQfM .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CFHLw9rtyZWuJQfM .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-CFHLw9rtyZWuJQfM .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CFHLw9rtyZWuJQfM .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-CFHLw9rtyZWuJQfM .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-CFHLw9rtyZWuJQfM .cluster text{fill:#333;}#mermaid-svg-CFHLw9rtyZWuJQfM .cluster span{color:#333;}#mermaid-svg-CFHLw9rtyZWuJQfM div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-CFHLw9rtyZWuJQfM .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-CFHLw9rtyZWuJQfM rect.text{fill:none;stroke-width:0;}#mermaid-svg-CFHLw9rtyZWuJQfM .icon-shape,#mermaid-svg-CFHLw9rtyZWuJQfM .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CFHLw9rtyZWuJQfM .icon-shape p,#mermaid-svg-CFHLw9rtyZWuJQfM .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-CFHLw9rtyZWuJQfM .icon-shape rect,#mermaid-svg-CFHLw9rtyZWuJQfM .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CFHLw9rtyZWuJQfM .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-CFHLw9rtyZWuJQfM .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-CFHLw9rtyZWuJQfM :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    命中

    未命中

    命中

    未命中

    用户请求

    L1本地缓存

    返回数据

    L2分布式缓存

    返回数据

    查询数据库

    更新缓存

    返回数据

    典型架构:

    • L1缓存:本地缓存(Caffeine/Guava),过期时间短
    • L2缓存:分布式缓存(Redis),过期时间较长
    • L3存储:数据库,最终数据源

    核心优势:

    • 多层防护,抗冲击能力强
    • L1缓存可拦截大量重复请求

    局限性:

    • 实现复杂度高
    • 需处理多级缓存一致性问题

    方案三:Redis高可用架构

    原理:通过部署Redis集群、主从复制、哨兵模式等,避免单点故障导致的服务不可用。

    Redis哨兵模式高可用架构图:

    #mermaid-svg-m8GtUiWBLEY5MSU7{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-m8GtUiWBLEY5MSU7 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-m8GtUiWBLEY5MSU7 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-m8GtUiWBLEY5MSU7 .error-icon{fill:#552222;}#mermaid-svg-m8GtUiWBLEY5MSU7 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-m8GtUiWBLEY5MSU7 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-m8GtUiWBLEY5MSU7 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-m8GtUiWBLEY5MSU7 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-m8GtUiWBLEY5MSU7 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-m8GtUiWBLEY5MSU7 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-m8GtUiWBLEY5MSU7 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-m8GtUiWBLEY5MSU7 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-m8GtUiWBLEY5MSU7 .marker.cross{stroke:#333333;}#mermaid-svg-m8GtUiWBLEY5MSU7 svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-m8GtUiWBLEY5MSU7 p{margin:0;}#mermaid-svg-m8GtUiWBLEY5MSU7 .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-m8GtUiWBLEY5MSU7 .cluster-label text{fill:#333;}#mermaid-svg-m8GtUiWBLEY5MSU7 .cluster-label span{color:#333;}#mermaid-svg-m8GtUiWBLEY5MSU7 .cluster-label span p{background-color:transparent;}#mermaid-svg-m8GtUiWBLEY5MSU7 .label text,#mermaid-svg-m8GtUiWBLEY5MSU7 span{fill:#333;color:#333;}#mermaid-svg-m8GtUiWBLEY5MSU7 .node rect,#mermaid-svg-m8GtUiWBLEY5MSU7 .node circle,#mermaid-svg-m8GtUiWBLEY5MSU7 .node ellipse,#mermaid-svg-m8GtUiWBLEY5MSU7 .node polygon,#mermaid-svg-m8GtUiWBLEY5MSU7 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-m8GtUiWBLEY5MSU7 .rough-node .label text,#mermaid-svg-m8GtUiWBLEY5MSU7 .node .label text,#mermaid-svg-m8GtUiWBLEY5MSU7 .image-shape .label,#mermaid-svg-m8GtUiWBLEY5MSU7 .icon-shape .label{text-anchor:middle;}#mermaid-svg-m8GtUiWBLEY5MSU7 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-m8GtUiWBLEY5MSU7 .rough-node .label,#mermaid-svg-m8GtUiWBLEY5MSU7 .node .label,#mermaid-svg-m8GtUiWBLEY5MSU7 .image-shape .label,#mermaid-svg-m8GtUiWBLEY5MSU7 .icon-shape .label{text-align:center;}#mermaid-svg-m8GtUiWBLEY5MSU7 .node.clickable{cursor:pointer;}#mermaid-svg-m8GtUiWBLEY5MSU7 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-m8GtUiWBLEY5MSU7 .arrowheadPath{fill:#333333;}#mermaid-svg-m8GtUiWBLEY5MSU7 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-m8GtUiWBLEY5MSU7 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-m8GtUiWBLEY5MSU7 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-m8GtUiWBLEY5MSU7 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-m8GtUiWBLEY5MSU7 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-m8GtUiWBLEY5MSU7 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-m8GtUiWBLEY5MSU7 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-m8GtUiWBLEY5MSU7 .cluster text{fill:#333;}#mermaid-svg-m8GtUiWBLEY5MSU7 .cluster span{color:#333;}#mermaid-svg-m8GtUiWBLEY5MSU7 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-m8GtUiWBLEY5MSU7 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-m8GtUiWBLEY5MSU7 rect.text{fill:none;stroke-width:0;}#mermaid-svg-m8GtUiWBLEY5MSU7 .icon-shape,#mermaid-svg-m8GtUiWBLEY5MSU7 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-m8GtUiWBLEY5MSU7 .icon-shape p,#mermaid-svg-m8GtUiWBLEY5MSU7 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-m8GtUiWBLEY5MSU7 .icon-shape rect,#mermaid-svg-m8GtUiWBLEY5MSU7 .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-m8GtUiWBLEY5MSU7 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-m8GtUiWBLEY5MSU7 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-m8GtUiWBLEY5MSU7 :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    哨兵集群

    Sentinel 1

    Sentinel 2

    Sentinel 3

    客户端

    Redis主节点

    Redis从节点1

    Redis从节点2

    架构选择:

    • 主从+哨兵:自动故障转移,保障服务连续性
    • Redis Cluster:数据分片,水平扩展
    • 多机房部署:跨机房容灾

    核心优势:

    • 从根源上避免因Redis宕机导致的雪崩
    • 提升整体系统可用性

    方案四:限流降级

    原理:当数据库压力过大时,主动丢弃部分请求,保证核心业务可用。

    常用策略:

    • 限流:限制每秒请求数(令牌桶/滑动窗口)
    • 降级:非核心业务返回默认值或缓存旧数据
    • 熔断:当错误率达到阈值时,快速失败

    核心优势:

    • 保护数据库不被击垮
    • 保证系统整体可用性

    五、三种问题的对比总结

    对比维度缓存穿透缓存击穿缓存雪崩
    问题根源 数据不存在 单个热点Key过期 大量Key同时过期/Redis宕机
    影响范围 单个Key(但可无限次请求) 单个热点Key 整体缓存服务
    并发特征 可高可低 瞬间超高并发 整体流量冲击
    首要解决方案 布隆过滤器 互斥锁 过期时间随机化
    辅助方案 缓存空对象 逻辑过期 多级缓存
    兜底方案 限流降级 热点Key永不过期 高可用集群

    六、生产环境最佳实践

    6.1 分层防御策略

    在实际生产环境中,应该采用分层防御的策略:

    层次防御手段针对问题
    入口层 布隆过滤器 拦截穿透请求
    缓存层 过期时间随机化、多级缓存 预防雪崩
    热点层 互斥锁、逻辑过期 处理击穿
    数据库层 限流、熔断、降级 终极保护

    6.2 监控与告警

    建立完善的监控体系,及时发现异常:

    • 缓存命中率:突然下降可能预示问题
    • 数据库QPS:异常飙升需立即告警
    • Redis内存/连接数:资源瓶颈预警
    • 慢查询日志:发现异常访问模式

    6.3 压测与演练

    定期进行压力测试和故障演练:

    • 模拟缓存穿透攻击
    • 模拟热点Key失效场景
    • 模拟Redis节点宕机
    • 验证限流降级策略有效性

    七、总结

    缓存雪崩、缓存穿透、缓存击穿是高并发系统设计中必须面对的三大挑战。它们看似相似,但成因和解决方案各不相同:

    问题一句话总结核心解决方案
    缓存穿透 查询不存在的数据 布隆过滤器前置拦截
    缓存击穿 单个热点Key过期 互斥锁或逻辑过期
    缓存雪崩 大量Key同时失效 过期时间随机化 + 高可用集群

    在实际生产环境中,这三大问题往往同时存在或相互诱发。最佳实践是组合使用多种方案,构建多层次的防御体系,同时配合完善的监控和限流降级机制,才能确保缓存系统的稳定可靠。


    赞(0)
    未经允许不得转载:171主机测评 » 缓存雪崩、缓存穿透、缓存击穿:高并发下的缓存稳定性深度解析
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址