专栏首页艾小仙没人告诉过你更复杂的缓存穿透怎么解决

没人告诉过你更复杂的缓存穿透怎么解决

你应该从网上看过太多的文章说缓存穿透怎么解决?无非就是布隆过滤器,缓存空值什么的。

但是,更深入的一个问题,缓存空值有没有问题?如果缓存的空值太多怎么办?

如果用的redis,那么太多的空值会不会打爆你的redis?如果用的本地缓存,会不会打爆你的内存?继而引发的问题就是还是会打爆你的数据库。

从线上问题说起

前不久,我们线上环境压测,在QPS压倒2W之后RT达到了几十秒,排查后发现是redis的连接数不够导致大量的连接超时。

经过考虑之后,我们最终决定弃用redis缓存的方案,改为本地缓存,因为我们缓存的都是一些配置信息,实际上几个月都不太可能修改,而redis配置的连接数是200,5分钟超时,数据量实际上也就只有几千条而已,实际上来说并没有很大的必要,本地缓存完全就可以解决问题了。

本地缓存使用Guava的LoadingCache实现。

但是修改完之后,压测之后还是发现有接口全部走到数据库查询,先排查代码,是否是代码的BUG导致实际没有生效,后来发现实际上发生了缓存穿透,压测使用了一些数据库中不存在的记录,导致了穿透的问题,实际上这个问题在使用redis的时候也一直存在,只是由于连接数的问题一直没有发现而已。

接下来就是考虑怎么解决的问题?

由于我们都是缓存的一些配置信息,几千条数据而已,最终考虑简单解决的办法。直接把所有的key全部从数据库查出来缓存下来,查数据库之前直接根据key过滤一把,如果不存在就直接返回,不要走数据库查询了。

当然,这是由于我们的场景比较简单,这样直接处理就行了,那么,如果再复杂一点,比如上亿的缓存数据呢?

解决方案

前置过滤

如果说类似我这种比较简单的一些缓存,使用我上面说的解决方案也可以,还有一些缓存的key是比如ID之类,也可以根据一定的范围规则去提前过滤,比如缓存的key明确知道在1-10万的范围之后,那么过滤掉在这个范围之外的请求直接返回就可以了。

当然,很明显这种简单的规则过滤适用于数据量不是很大,并且数据不会频繁发生改变的情况。

布隆过滤器

对于上述场景,因为数据量很小,简单的代码实现缓存即可,如果说数据量很大的话,比如有一亿个key,使用布隆过滤器就是个更优解。

我们可以每天定时把所有的配置信息从数据库中查询出来构建成bitmap。

关于布隆过滤器我前面的文章也有写过,贴上之前的图一张,如果查询的位置都是1的话说明key存在,反之只要有一个0则说明肯定不存在。

使用布隆过滤器的缺点也很明显,存在一定概率的误判。当然,既然用了,对于误判比例、内存占用等等问题应该事先评估好。

缓存空值

这个是网上说烂的问题,但是缓存空值的空值太多明显也是有问题的,再进一步解决方案就是快速过期。

一般来说,普通的缓存的写法如下,先查缓存,如果缓存存在则直接返回,如果缓存没有则去数据库查询,结果不是空就保存到缓存中。

改进版的写法就是缓存空对象,针对空的数据,设置过期时间,比如10分钟,快速过期,防止太多的空值问题。

但是这个解决方案仍然有点小问题,就是短暂的数据不一致的问题。

想象一下如果缓存的空值这时候实际上已经有值了,那么在过期时间的这段时间内就可能存在短暂的数据不一致。

总结

缓存穿透的问题总结下来就是三点,这三个方式不是说是隔离的解决方案,他们可以结合在一起使用。

首先看数据量,如果数据量很小并且没有频繁变更的话,选择前置过滤的方式,根据具体的业务规则来处理就可以。

如果数据量大的话,可以选择使用布隆过滤器,但是存在一定概率的误判。

通过前置的拦截,应该拦截住大部分的流量,避免直接打爆数据库。

最后,可以使用缓存空值并且设置快速过期的方式来作为一个兜底的方案。

如果还有问题,那么就是限流、降级了。

- END -

本文分享自微信公众号 - 艾小仙(aixiaoxianren),作者:艾小仙

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-01-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 女朋友携程三面被Redis难倒!回来给她讲了一晚上的缓存穿透、缓存击穿、缓存雪崩!

    周末在家面试,和候选人聊到Redis的问题,于是问了他一个问题:你知道缓存穿透、缓存击穿和缓存雪崩吗?他们之间的区别是什么?分别怎么解决吗?

    Java程序猿
  • 漫话:如何给女朋友解释什么是缓存穿透、缓存击穿、缓存雪崩?

    周末在家面试,和候选人聊到Redis的问题,于是问了他一个问题:你知道缓存穿透、缓存击穿和缓存雪崩吗?他们之间的区别是什么?分别怎么解决吗?

    CSDN技术头条
  • 还不懂Redis?看完这个故事就明白了

    在我还没来到这个世界上的时候,MySQL过的很辛苦,互联网发展的越来越快,它容纳的数据也越来越多,用户请求也随之暴涨,而每一个用户请求都变成了对它的一个又一个读...

    码农架构
  • 分布式系统关注点(18)——「缓存穿透」和「缓存雪崩」到底啥区别?

    有句话说得好,欲要使其毁灭,先要使其疯狂。当你沉浸在缓存所带来的系统tps飙升的喜悦中时,使你系统毁灭的种子也已经埋在其中。

    Zachary_ZF
  • 当周杰伦把QQ音乐干翻的时候,作为程序猿我看到了什么?

            再等二分钟,别人都会唱了,我还没付钱!不要这样吧!QQ音乐你要振作起来啊!

    why技术
  • 我是Redis,MySQL大哥被我害惨了!

    在我还没来到这个世界上的时候,MySQL过的很辛苦,互联网发展的越来越快,它容纳的数据也越来越多,用户请求也随之暴涨,而每一个用户请求都变成了对它的一个又一个读...

    轩辕之风
  • 烦人的缓存穿透问题,今天教就你如何去解决

    前几天我们讲到了缓存的读写策略(你一定要掌握这种缓存读写策略,开发必备)以及如何搭建高可用缓存系统(分布式缓存高可用方案,我们都是这么干的),都是为了能在基础架...

    架构师修炼
  • 字节提前批二面:你的项目是怎么解决缓存穿透的?

    陌溪之前在面试字节提前批的时候,二面的面试官就问过 Redis 缓存穿透的问题,下面让我们一起深度还原一下陌溪当初的面试场景吧~

    拓跋阿秀
  • [需求设计]从一个小需求感受Redis的独特魅力

    Redis在实际应用中使用的非常广泛,本篇文章就从一个简单的需求说起,为你讲述一个需求是如何从头到尾开始做的,又是如何一步步完善的。之前写过一篇《如何实现页面广...

    编程大道
  • 大厂面试系列(六):Redis及nosql应用

    zhaozhen
  • Redis面试题汇总(附答案),面试突击专用

    Redis是一个支持持久化的内存数据库,通过持久化机制把内存中的数据同步到硬盘文件来保证数据持久化。当Redis重启后通过把硬盘文件重新加载到内存,就能达到恢复...

    程序员白楠楠
  • 读者让我总结一波 redis 面试题,现在肝出来了!

    Redis是一个支持持久化的内存数据库,通过持久化机制把内存中的数据同步到硬盘文件来保证数据持久化。当Redis重启后通过把硬盘文件重新加载到内存,就能达到恢复...

    cxuan
  • 什么是缓存击穿、雪崩、穿透

    随着互联网的越来越普及,用户越来越多,系统性能瓶颈成了越来越热门的话题。要解决性能问题的技术手段有很多,比如:缓存、CDN加速、页面静态化、集...

    苏三说技术
  • Redis系列 | 缓存穿透、击穿、雪崩、预热、更新、降级

    Redis是高性能的分布式内存数据库,对于内存数据库经常会出现下面几种情况,也经常会出现在Redis面试题中:缓存穿透、缓存击穿、缓存雪崩、缓存预热、缓存更新、...

    王知无-import_bigdata
  • 修正版 | QPS过万,Redis大量连接超时怎么解决?

    之前负责的一个服务总是在高峰时刻和压测发生大量的redis连接超时的异常redis.clients.jedis.exceptions.JedisConnecti...

    艾小仙
  • Redis进阶-布隆过滤器

    我们在 Redis进阶-Redis缓存优化中 讲到了 缓存穿透 的解决防范: 比缓存空值更好的一种解决方式 布隆过滤器 ,这里我们详细讲解下。

    小小工匠
  • 缓存穿透、击穿、雪崩什么的傻傻分不清楚?

    对于缓存,大家肯定都不陌生,不管是前端还是服务端开发,缓存几乎都是必不可少的优化方式之一。在实际生产环境中,缓存的使用规范也是一直备受重视的,如果使用的不好,很...

    Java3y
  • 程序员,被代码耽误的段子手

    来自:简书,作者:kuntoria 链接:https://www.jianshu.com/p/ab2a1c1e87fa

    昱良
  • Redis使用|缓存穿透,雪崩,击穿以及解决方案分析

    作为一种非关系型数据库,redis也总是免不了有各种各样的问题,这篇文章主要是针对其中三个问题进行讲解:缓存穿透、缓存击穿和缓存雪崩,并给出一些解决方案。

    浅羽技术

扫码关注云+社区

领取腾讯云代金券