Redis 从 0 到 1(十一):缓存穿透/击穿/雪崩三连击,Go 3 套防御代码

发布时间:2026/10/17 2:38:17
Redis 从 0 到 1(十一):缓存穿透/击穿/雪崩三连击,Go 3 套防御代码 我不会起名字322· 后端 / 算法 / 数据库 技术栈 力扣 Hot100 Go 项目 Redis MySQL文章目录Redis 从 0 到 1十一缓存穿透/击穿/雪崩三连击Go 3 套防御代码一、三个事故三种机理二、Go 实操 1布隆过滤器挡穿透收藏点 1三、Go 实操 2互斥重建挡击穿收藏点 2四、Go 实操 3随机 TTL 防雪崩一行的事五、压测对比收藏点 3六、排查步骤缓存相关数据库打满从哪查七、总结Redis 从 0 到 1十一缓存穿透/击穿/雪崩三连击Go 3 套防御代码上一篇《Redis 从 0 到 1十16384 个槽怎么分6 节点 Cluster 与 Go 重定向处理》我们打完了部署篇的最后一块拼图链接https://blog.csdn.net/2501_92769340/article/details/167399592 。本篇进入实战弧线第一题就是 Redis 面试和线上事故的双料冠军缓存穿透、击穿、雪崩。一、三个事故三种机理它们名字像其实是完全不同的病问题事故形态根因缓存穿透攻击者用-1、null之类的 key 狂刷接口数据库被拖垮key 本身不存在缓存永远不命中每次请求都落到数据库缓存击穿某热 key 过期瞬间1000 个并发同时查库重建数据库瞬时被打爆高并发 重建成本高 没有互斥缓存雪崩半夜一批 key 同时过期比如批量导入时同 TTL大量请求同时打到数据库过期时间集中 无降级对策也一一对应穿透用布隆过滤器把不存在的 key挡在缓存层之前击穿过期的瞬间只允许一个请求去重建雪崩把过期时间打散。二、Go 实操 1布隆过滤器挡穿透收藏点 1思路查询前先问过滤器——“这个 key 可能存在吗”。答案一定不存在就直接返回根本不去碰缓存和数据库答案可能存在才走正常缓存流程。过滤器用 Redis 的 Bitmap 实现SETBIT/GETBIT不引入 RedisBloom 模块只要 String 类型支持即可。packagebloomimport(contexthash/crc32hash/fnvgithub.com/redis/go-redis/v9)// 双哈希函数定位两个 bit 位误判率约 1e-4 量级够用即可别追求精确funcoffsets(keystring)(uint32,uint32){h1:fnv.New32a();h1.Write([]byte(key))h2:crc32.ChecksumIEEE([]byte(key))size:uint32(122)// 4M bit ≈ 512KB 一个位图returnh1.Sum32()%size,h2.Sum32()%size}// Add 把 key 加进过滤器数据加载时同步调用funcAdd(ctx context.Context,rdb*redis.Client,keystring)error{a,b:offsets(key)bitKey:bloom:userspipe:rdb.Pipeline()pipe.SetBit(ctx,bitKey,int64(a),1)pipe.SetBit(ctx,bitKey,int64(b),1)_,err:pipe.Exec(ctx)returnerr}// MightExist 一定不存在返回 false可能存在返回 true有误判无漏判funcMightExist(ctx context.Context,rdb*redis.Client,keystring)(bool,error){a,b:offsets(key)// 两个 bit 都为 1 才认为可能存在Pipeline 一次 RTT 查两个位pipe:rdb.Pipeline()va:pipe.GetBit(ctx,bloom:users,int64(a))vb:pipe.GetBit(ctx,bloom:users,int64(b))if_,err:pipe.Exec(ctx);err!nil{returnfalse,err}returnva.Val()1vb.Val()1,nil}查询入口改造funcGetUser(ctx context.Context,rdb*redis.Client,idstring)(string,error){ok,err:bloom.MightExist(ctx,rdb,user:id)iferr!nil{return,err}if!ok{return,nil// 布隆说一定不存在直接空结果不碰数据库}val,err:rdb.Get(ctx,user:id).Result()// ... 未命中再回源回源为空时写短 TTL 空值缓存见下_valreturnval,err}两级防线配合使用更稳布隆挡掉绝对不存在的 key对漏过的攻击再补空值缓存数据库查不到也缓存 30 秒key 命中率立刻归零。三、Go 实操 2互斥重建挡击穿收藏点 2击穿的本质是1000 个人同时发现缓存没了一起去查库。解法只允许第一个人去查其他人等结果。importgolang.org/x/sync/singleflightvargroup singleflight.GroupfuncGetProduct(ctx context.Context,rdb*redis.Client,skustring)(string,error){// singleflight同一 sku 的并发查询自动合并只有一个 goroutine 真正执行val,err,_:group.Do(product:sku,func()(any,error){cached,err:rdb.Get(ctx,product:sku).Result()iferrnil{returncached,nil}if!errors.Is(err,redis.Nil){returnnil,err}// 双重检查拿到互斥锁确认自己重建防止 singleflight 合并前已有人重建ok,err:rdb.SetNX(ctx,lock:product:sku,1,5*time.Second).Result()iferr!nil{returnnil,err}if!ok{time.Sleep(50*time.Millisecond)// 等持锁者写完再读一次缓存returnrdb.Get(ctx,product:sku).Result()}deferrdb.Del(ctx,lock:product:sku)// 回源数据库省略写入缓存返回return,nil})iferr!nil{return,err}returnval.(string),nil}注意点singleflight 合并的是进程内并发跨实例部署时SetNX 互斥锁是第二道保险第 13 篇把它升级成完整分布式锁。四、Go 实操 3随机 TTL 防雪崩一行的事// 基础 TTL 30 分钟加 ±5 分钟随机抖动避免整批 key 同时到期ttl:30*time.Minutetime.Duration(rand.Int63n(10*60))*time.Second-5*time.Minute rdb.SetEx(ctx,key,val,ttl)同时给批量导入场景立规矩导入 100 万个 key 时TTL 用base i*offset错开而不是统一 24 小时。五、压测对比收藏点 3模拟热 key 过期瞬间 500 并发查询数据库回源模拟为 100ms对比三种状态防御方案数据库瞬时 QPS接口 P99无防御500全穿透100ms 排队互斥重建≈1105ms互斥重建 降级空值≈1异常时 05ms降级雪崩场景5000 个 key 同刻过期无抖动vs TTL 抖动数据库请求峰值从 5000 QPS 降到 50。六、排查步骤缓存相关数据库打满从哪查看数据库慢查询是否大量相同 SQL 查不存在的 id → 穿透看缓存命中率曲线从 95% 跳水 → 大面积失效雪崩看单 key 访问热度某个 key QPS 异常高且刚过期 → 击穿对症下药穿透加布隆 空值缓存击穿加互斥重建雪崩加 TTL 抖动 多级缓存。七、总结三个问题三种病穿透是查不存在的击穿是热 key 过期瞬间雪崩是一起过期防御三板斧布隆过滤器 空值缓存、singleflight SetNX 互斥重建、随机 TTL 抖动过滤器有不存在的误判但没有漏判空值缓存兜住误判两级配合最稳所有防御代码都是幂等的故障时可以随时降级。下一篇预告缓存挡住了恶意流量但缓存和数据库之间还有一笔糊涂账——先删缓存还是先更新库下一篇《先删缓存还是先更新库4 种方案的 Go 并发实测》我们用 100 个 goroutine 把四种方案的脏读概率打出来。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询