缓存穿透了怎么办?

出口成章
• 阅读 1156

在现在互联网架构中,几乎每个互联网项目都会引入缓存系统,比如 Redis、Memcached。来保护下游数据库和提升系统并发量。不管使用哪种缓存系统都有可能遇到缓存穿透的问题。

缓存穿透是指在缓存系统中没有查询到数据,而不得不将请求打到数据库上查询的情况。

当然缓存系统是不可避免的,少量的缓存穿透对系统也没有损害,不可避免的原因有以下几点:

  • 缓存系统的容量是有限的,不可能存储系统所有的数据,那么在查询未缓存数据的时候就会发生缓存穿透。
  • 另一方面就是基于‘二八原则’,我们通常只会缓存常用的那 20% 的热点数据。

正常情况下的缓存穿透是没什么伤害的,但是如果你的系统遭遇攻击,存在大量的缓存穿透的话,那么可能就是一个麻烦了,如果大量的缓存穿透超过了后端服务器的承受能力,那么就有可能造成服务崩溃,这是不可接受的。

基于存在这种大量缓存穿透的可能性,所以我们就需要从根源上解决缓存穿透的问题,解决缓存穿透,目前一般有两种方案:缓存空值和使用布隆过滤器

缓存空值

如果我们系统是遇到攻击的话,那么很有可能查询的值是伪造的,必然大概率不存在我们的系统中,这样无论查询多少次,在缓存中一直不存在,这样缓存穿透就一直存在。

在这种情况下,我们可以在缓存系统中缓存一个空值,防止穿透一直存在,但是因为空值并不是准确的业务数据,并且会占用缓存的空间,所以我们会给这个空值加一个比较短的过期时间,让空值在短时间之内能够快速过期淘汰。下面是一段伪代码:

Object nullValue = new Object();
try {
  Object valueFromDB = getFromDB(uid); //从数据库中查询数据
  if (valueFromDB == null) {
    cache.set(uid, nullValue, 10);   //如果从数据库中查询到空值,就把空值写入缓存,设置较短的超时时间
  } else {
    cache.set(uid, valueFromDB, 1000);
  }
} catch(Exception e) {
  cache.set(uid, nullValue, 10);
}

虽然这种方法可以解决缓存穿透的问题,但是这种方式也存在弊端,因为在缓存系统中存了大量的空值,浪费缓存的存储空间,如果缓存空间被占满了,还会还会剔除掉一些已经被缓存的用户信息反而会造成缓存命中率的下降。

使用布隆过滤器

1970年布隆提出了一种布隆过滤器的算法,用来判断一个元素是否在一个集合中。布隆过滤器底层是一个超级大的 bit 数组,默认值都是 0 ,一个元素通过多个hash函数映射到这个 bit 数组上,并且将 0 改成 1。当然布隆过滤器也不需要我们实现,在 Google 的 guava 包中有提供布隆过滤器,有兴趣的小伙伴可以研究研究。

布隆过滤器存在一定的误判,因为采用hash算法,就一定会存在哈希冲突,这样就可能造成不在数据库中的元素被判断在布隆过滤器中存在,但是不在布隆过滤器中的元素一定不存在数据库中。

利用布隆过滤器的这个特点可以解决缓存穿透的问题,在服务启动的时候先把数据的查询条件,例如数据的 ID 映射到布隆过滤器上,当然如果新增数据时,除了写入到数据库中之外,也需要将数据的ID存入到布隆过滤器中

我们在查询某条数据时,先判断这个查询的 ID 是否存在布隆过滤器中,如果不存在就直接返回空值,而不需要继续查询数据库和缓存,存在布隆过滤器中才继续查询数据库和缓存,这样就解决缓存穿透的问题。

缓存穿透了怎么办?

当然布隆过滤器有缺陷,除了上面我们讲到过的存在一定的误判,还有一个就是不支持删除

缓存空值和使用布隆过滤器都可以在一定程度上解决缓存穿透的问题,各自有各自的优势,具体如何使用根据特定的场景舍取。

以上就是今天分享的内容,希望对您的学习或者工作有所帮助,如果您觉得文章不错,欢迎点个赞和转发,谢谢。

最后

目前互联网上很多大佬都有缓存穿透相关文章,如有雷同,请多多包涵了。原创不易,码字不易,还希望大家多多支持。若文中有所错误之处,还望提出,谢谢。

缓存穿透了怎么办?

点赞
收藏
评论区
推荐文章
3A网络 3A网络
2年前
缓存三大问题及解决方案
1.缓存来由随着互联网系统发展的逐步完善,提高系统的qps,目前的绝大部分系统都增加了缓存机制从而避免请求过多的直接与数据库操作从而造成系统瓶颈,极大的提升了用户体验和系统稳定性。2.缓存问题虽然使用缓存给系统带来了一定的质的提升,但同时也带来了一些需要注意的问题。2.1缓存穿透缓存穿透是指查询一个一定不存在的数据,因为缓存中也无该数据的信息,则会
Stella981 Stella981
3年前
SpringBoot缓存篇Ⅱ
一.Redis环境搭建系统默认是使用ConcurrentMapCacheManager,然后获取和创建ConcurrentMapCache类型的缓存组件,再将数据保存在ConcurrentMap中开发中使用缓存中间件:redis,memcached,ehcache1.搭建redis环境在linux上安装redis(推荐使用do
Stella981 Stella981
3年前
Redis 击穿、穿透、雪崩的解决方案
Redis击穿、穿透、雪崩的解决方案击穿和穿透场景:指的是单个key在缓存中查不到,去数据库查询(透过redis去查db叫击穿)区别:击穿:数据在数据库中真实存在,缓存丢失,大量请求击穿数据库穿透:数据在缓存中没有,数据库中也没有
Easter79 Easter79
3年前
SpringBoot缓存篇Ⅱ
一.Redis环境搭建系统默认是使用ConcurrentMapCacheManager,然后获取和创建ConcurrentMapCache类型的缓存组件,再将数据保存在ConcurrentMap中开发中使用缓存中间件:redis,memcached,ehcache1.搭建redis环境在linux上安装redis(推荐使用do
Stella981 Stella981
3年前
Redis之缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级
\TOC\Redis之缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级1、缓存雪崩  发生场景:当Redis服务器重启或者大量缓存在同一时期失效时,此时大量的流量会全部冲击到数据库上面,数据库有可能会因为承受不住而宕机  解决办法:    1)随机均匀设置失效
Stella981 Stella981
3年前
Redis 缓存穿透、缓存雪崩的概念及其预防
缓存穿透【什么是缓存穿透】频繁查询不在缓存中的数据,给原本被缓存保护的系统过大压力。【为什么会发生缓存穿透】1\.程序没写好;2\.恶意攻击。【怎样防止缓存穿透】1\.在对key进行查询之前,先做初步判断,如果key一定不存在(例如,对某表的缓存,key一定由数字组成,那么包含非数字的key一定是不存在的
Stella981 Stella981
3年前
Redis缓存穿透、缓存雪崩和缓存击穿
Redis缓存穿透、缓存雪崩缓存雪崩,是指在某一个时间段,缓存集中过期失效。产生雪崩的原因之一,比如在写本文的时候,马上就要到双十二零点,很快就会迎来一波抢购,这波商品时间比较集中的放入了缓存,假设缓存一个小时。那么到了凌晨一点钟的时候,这批商品的缓存就都过期了。而对这批商品的访问查询,都落到了数据库上,对于数据库而言,
Stella981 Stella981
3年前
Linux玩转redis从入门到放肆
1\.缓存穿透在大多数互联网应用中,缓存的使用方式如下图所示:!(https://oscimg.oschina.net/oscnet/6a12e0fbee579fa624b2ea1738e89278c3f.png)1.当业务系统发起某一个查询请求时,首先判断缓存中是否有该数据;2.如果缓存中存在,则直接返回数据;3.如果缓存中
Stella981 Stella981
3年前
Redis缓存穿透问题及解决方案
上周在工作中遇到了一个问题场景,即查询商品的配件信息时(商品:配件为1:N的关系),如若商品并未配置配件信息,则查数据库为空,且不会加入缓存,这就会导致,下次在查询同样商品的配件时,由于缓存未命中,则仍旧会查底层数据库,所以缓存就一直未起到应有的作用,当并发流量大时,会很容易把DB打垮。缓存穿透问题缓存穿透是指查询一个根本不存在的数
【专项测试系列】-缓存击穿、穿透、雪崩专项测试
作者:刘须华一、背景概述: R2M缓存的使用,极大的提升了应用程序的性能和效率,特别是数据查询方面。而缓存最常见的问题是缓存穿透、击穿和雪崩,在高并发下这三种情况都会有大量请求落到数据库,导致数据库资源占满,引起数据库故障。平时
Redis缓存的主要异常及解决方案
Redis是当前最流行的NoSQL数据库。Redis主要用来做缓存使用,在提高数据查询效率、保护数据库等方面起到了关键性的作用,很大程度上提高系统的性能。当然在使用过程中,也会出现一些异常情景,导致Redis失去缓存作用。
出口成章
出口成章
Lv1
山水总相逢,来日皆可期。
文章
4
粉丝
0
获赞
0