Redis 命中率 99%,数据库却 100% CPU,是谁在捣鬼

发布时间:2026/7/27 16:58:21

Redis 命中率 99%,数据库却 100% CPU,是谁在捣鬼 前阵子我在公司排查一次线上事故事情特别“离谱”Redis 正常、代码没改、数据库却 CPU 100%连接数飙升服务雪崩式超时。当时我第一反应是“是不是缓存挂了是不是缓存雪崩”结果一查 Redis稳如老狗命中率还挺高。那数据库为啥还能被打爆最后答案四个字缓存穿透。这也是 Java 社招面试里Redis 相关问题出现频率极高的一道题。先讲个故事快递站被“查不存在的包裹”查垮了为了把缓存穿透讲清楚我先给你讲个生活中的故事。假设你家楼下有一个快递站前台小哥缓存 Redis仓库后面的仓储区数据库 MySQL你用户发起查询请求正常流程是这样的你问小哥“有我这个包裹吗”小哥一查系统Redis有 → 直接给你没有 → 去仓库查数据库仓库查到了 → 拿出来给你同时小哥把信息记下来下次就不用再跑仓库但有一天事情开始不对劲了……突然来了一群人天天问“有单号 -1 的包裹吗”“有单号 999999999999 的包裹吗”“有单号 0 的包裹吗”这些包裹根本不存在。结果发生了什么小哥查不到缓存没有每次都得跑仓库仓库也查不到但你没有任何机制告诉小哥这玩意本来就不存在于是所有请求100% 穿过前台全部打到仓库仓库再大也扛不住这种“查空气”的请求。这就是缓存穿透。什么是缓存穿透面试标准答案缓存穿透是指查询的数据在缓存和数据库中都不存在导致每次请求都会绕过缓存直接访问数据库从而在高并发下对数据库造成巨大压力甚至导致数据库崩溃。特点非常明显查的是不存在的数据缓存里没有数据库里也没有缓存失效策略对它完全没用缓存穿透为什么这么危险我们用一张表来对比一下几种常见缓存问题缓存穿透最恶心的一点是它是“可被人为制造”的攻击。只要有人不断请求不存在的 ID你的数据库就会被持续消耗。解决方案一接口层增加基础校验第一道防线先说一句非常现实的话很多缓存穿透本来就不应该进系统。1、常见的非法请求长这样id 0id 不是数字用户未登录token 非法参数明显不合理2、在接口层直接拦截这是最便宜、最有效的一层防护。如果你连 id 0 都放进 Redis 和数据库里查那不是技术问题是态度问题3、这一层的特点但注意这一层永远不够。解决方案二缓存空值key-null 策略这是面试里必考的一种方案。1、核心思想一句话既然这个数据不存在那我就明确告诉缓存它不存在。2、查询流程升级版查 Redis有值 → 返回是 null → 直接返回空Redis 没有 → 查数据库数据库也没有把 key-null 写进 Redis设置较短过期时间比如 30 秒3、示例代码4、为什么过期时间要短因为这个数据可能未来会被创建如果你缓存 null 一小时那真实数据出现后用户一小时都查不到5、优缺点分析解决方案三布隆过滤器终极方案面试加分项如果你在面试中能把Bloom Filter讲清楚面试官大概率会在心里默默给你加分。1、先回到刚才的快递故事如果快递站门口有一块超大的白板所有可能存在的包裹单号都提前在白板上“打过标记”那么你来查一个单号白板一看根本没标记小哥直接告诉你不用进站肯定没有这块白板就是布隆过滤器。Bitmap 与 Bloom Filter 的极致空间利用1、Bitmap 是什么Bitmap 本质上是用 1 bit 表示一个元素是否存在典型应用用户是否签到某天是否打卡某个 ID 是否出现过2、Bitmap 的问题布隆过滤器Bloom Filter原理详解1、核心思想用多个 Hash 函数降低冲突概率。不是一个 Hash而是k 个 Hash 函数。2、工作流程插入元素时用 k 个 Hash 函数计算得到 k 个位置把 bitmap 对应位置全部置为 1查询元素时只要有一个 bit 为 0一定不存在如果全部为 1可能存在3、关键结论面试必背不存在 → 一定准确存在 → 有一定误判率为什么 Bloom Filter 能防缓存穿透因为所有可能存在的数据在系统启动时就已经加入 Bloom Filter请求来了先过 Bloom Filter请求流程变成请求进来先查 Bloom Filter不存在 → 直接返回可能存在 → 再查 Redis / DB数据库终于可以喘口气了。Bloom Filter 的优缺点总结Redis 中使用 Bloom Filter实践建议在实际项目中一般有两种方式自己实现 Bitmap Hash使用 RedisBloom 插件示意代码简化在接口最前面加一层三种方案如何组合使用标准答案真正的生产环境从来不是“选一个”。而是一句话总结层层过滤让请求越早死越好。面试时怎么一句话总结缓存穿透你可以这么说缓存穿透是指查询缓存和数据库中都不存在的数据导致请求绕过缓存直接访问数据库。我通常通过接口参数校验、缓存空值以及使用布隆过滤器三种方式结合解决。其中布隆过滤器用于从源头拦截不存在的数据是大规模系统中最常见的方案。如果你这么说面试官基本会点头。总结缓存穿透这件事本质上不是 Redis 的问题而是你有没有认真思考过哪些请求根本不该进数据库。数据库很贵也很脆弱。Redis 再快也扛不住“查空气”。END希望这篇文章能帮你在面试中稳稳拿下这一题也能在真实项目里少踩一次坑。作者软件求生链接https://juejin.cn/post/7586934804290895906来源稀土掘金著作权归作者所有。商业转载请联系作者获得授权非商业转载请注明出处。前阵子我在公司排查一次线上事故事情特别“离谱”Redis 正常、代码没改、数据库却 CPU 100%连接数飙升服务雪崩式超时。当时我第一反应是“是不是缓存挂了是不是缓存雪崩”结果一查 Redis稳如老狗命中率还挺高。那数据库为啥还能被打爆最后答案四个字缓存穿透。这也是 Java 社招面试里Redis 相关问题出现频率极高的一道题。先讲个故事快递站被“查不存在的包裹”查垮了为了把缓存穿透讲清楚我先给你讲个生活中的故事。假设你家楼下有一个快递站前台小哥缓存 Redis仓库后面的仓储区数据库 MySQL你用户发起查询请求正常流程是这样的你问小哥“有我这个包裹吗”小哥一查系统Redis有 → 直接给你没有 → 去仓库查数据库仓库查到了 → 拿出来给你同时小哥把信息记下来下次就不用再跑仓库但有一天事情开始不对劲了……突然来了一群人天天问“有单号 -1 的包裹吗”“有单号 999999999999 的包裹吗”“有单号 0 的包裹吗”这些包裹根本不存在。结果发生了什么小哥查不到缓存没有每次都得跑仓库仓库也查不到但你没有任何机制告诉小哥这玩意本来就不存在于是所有请求100% 穿过前台全部打到仓库仓库再大也扛不住这种“查空气”的请求。这就是缓存穿透。什么是缓存穿透面试标准答案缓存穿透是指查询的数据在缓存和数据库中都不存在导致每次请求都会绕过缓存直接访问数据库从而在高并发下对数据库造成巨大压力甚至导致数据库崩溃。特点非常明显查的是不存在的数据缓存里没有数据库里也没有缓存失效策略对它完全没用缓存穿透为什么这么危险我们用一张表来对比一下几种常见缓存问题缓存穿透最恶心的一点是它是“可被人为制造”的攻击。只要有人不断请求不存在的 ID你的数据库就会被持续消耗。解决方案一接口层增加基础校验第一道防线先说一句非常现实的话很多缓存穿透本来就不应该进系统。1、常见的非法请求长这样id 0id 不是数字用户未登录token 非法参数明显不合理2、在接口层直接拦截这是最便宜、最有效的一层防护。如果你连 id 0 都放进 Redis 和数据库里查那不是技术问题是态度问题3、这一层的特点但注意这一层永远不够。解决方案二缓存空值key-null 策略这是面试里必考的一种方案。1、核心思想一句话既然这个数据不存在那我就明确告诉缓存它不存在。2、查询流程升级版查 Redis有值 → 返回是 null → 直接返回空Redis 没有 → 查数据库数据库也没有把 key-null 写进 Redis设置较短过期时间比如 30 秒3、示例代码4、为什么过期时间要短因为这个数据可能未来会被创建如果你缓存 null 一小时那真实数据出现后用户一小时都查不到5、优缺点分析解决方案三布隆过滤器终极方案面试加分项如果你在面试中能把Bloom Filter讲清楚面试官大概率会在心里默默给你加分。1、先回到刚才的快递故事如果快递站门口有一块超大的白板所有可能存在的包裹单号都提前在白板上“打过标记”那么你来查一个单号白板一看根本没标记小哥直接告诉你不用进站肯定没有这块白板就是布隆过滤器。Bitmap 与 Bloom Filter 的极致空间利用1、Bitmap 是什么Bitmap 本质上是用 1 bit 表示一个元素是否存在典型应用用户是否签到某天是否打卡某个 ID 是否出现过2、Bitmap 的问题布隆过滤器Bloom Filter原理详解1、核心思想用多个 Hash 函数降低冲突概率。不是一个 Hash而是k 个 Hash 函数。2、工作流程插入元素时用 k 个 Hash 函数计算得到 k 个位置把 bitmap 对应位置全部置为 1查询元素时只要有一个 bit 为 0一定不存在如果全部为 1可能存在3、关键结论面试必背不存在 → 一定准确存在 → 有一定误判率为什么 Bloom Filter 能防缓存穿透因为所有可能存在的数据在系统启动时就已经加入 Bloom Filter请求来了先过 Bloom Filter请求流程变成请求进来先查 Bloom Filter不存在 → 直接返回可能存在 → 再查 Redis / DB数据库终于可以喘口气了。Bloom Filter 的优缺点总结Redis 中使用 Bloom Filter实践建议在实际项目中一般有两种方式自己实现 Bitmap Hash使用 RedisBloom 插件示意代码简化在接口最前面加一层三种方案如何组合使用标准答案真正的生产环境从来不是“选一个”。而是一句话总结层层过滤让请求越早死越好。面试时怎么一句话总结缓存穿透你可以这么说缓存穿透是指查询缓存和数据库中都不存在的数据导致请求绕过缓存直接访问数据库。我通常通过接口参数校验、缓存空值以及使用布隆过滤器三种方式结合解决。其中布隆过滤器用于从源头拦截不存在的数据是大规模系统中最常见的方案。如果你这么说面试官基本会点头。总结缓存穿透这件事本质上不是 Redis 的问题而是你有没有认真思考过哪些请求根本不该进数据库。数据库很贵也很脆弱。Redis 再快也扛不住“查空气”。END希望这篇文章能帮你在面试中稳稳拿下这一题也能在真实项目里少踩一次坑。

相关新闻