面试官-什么是缓存穿透?怎么解决?

面试官-什么是缓存穿透?怎么解决?什么是缓存穿透 所谓的缓存穿透就是指在查询数据的时候 如果请求的 Key 在缓存和数据库中都不存在的话 就会导致每次的数据查询操作都会进行数据库查询 所导致的问题就是如果查询量级较大的话可能导致数据库的 I O 压力 造成系统性能瓶颈的同时 导

大家好,欢迎来到IT知识分享网。

面试官-什么是缓存穿透?怎么解决?

什么是缓存穿透?

  所谓的缓存穿透就是指在查询数据的时候,如果请求的Key在缓存和数据库中都不存在的话,就会导致每次的数据查询操作都会进行数据库查询,所导致的问题就是如果查询量级较大的话可能导致数据库的I/O压力,造成系统性能瓶颈的同时,导致缓存无法发挥作用的情况。

  比如,用户查询一个不存在的商品 ID(假设商品 ID 是 99999),缓存中没有命中,查询数据库也没有结果,数据库返回空,但因为没有缓存空结果,下次同样的请求又会穿透,重复给数据库带来压力。

  如果有大量的用户频繁的请求这个不存在的Key,那么这种情况下机会导致缓存失效,数据库压力激增,导致系统奔溃。为了解决这个问题,我们提供了如下的一些解决方案。

常见的解决方案

缓存空值

  我们可以将数据库查询为空的结果也缓存下来,比如缓存为 null 或者其他的特殊标识,同时设置较短的过期时间(比如几分钟)。这样在相同的key被再次查询时,可以直接从缓存返回,避免穿透到数据库。如下所示。

String key = "item:" + itemId; String cachedValue = redis.get(key); if (cachedValue == null) { // 查询数据库 String dbValue = queryFromDB(itemId); if (dbValue != null) { redis.set(key, dbValue, ttl); } else { redis.set(key, "null", shortTTL); // 缓存空值,设置短过期时间 } } 

  这种方式可以有效的拦截大部分的无效请求,但是存在的问题就是,如果有大量的随机请求进入之后,就会占用较多的Redis内存,导致缓存奔溃。

布隆过滤器(Bloom Filter)

  为了解决随机Key的问题,我们提出了布隆过滤器,布隆过滤器是一种概率型数据结构,可以快速判断某个 key 是否可能存在。如果布隆过滤器判断 key 不存在,就直接拦截请求,这样就可以避免访问缓存和数据库,如下所示。

BloomFilter<String> bloomFilter = new BloomFilter<>(expectedInsertions, falsePositiveProbability); // 初始化布隆过滤器,添加所有合法 key for (String id : allValidKeysFromDB) { bloomFilter.put(id); } // 查询逻辑 if (!bloomFilter.mightContain(itemId)) { return null; // 直接拦截请求 } String cachedValue = redis.get(key); // 缓存命中或访问数据库 

  这种方案可以高效的拦截一些不存在的Key,可以有效的避免大面积的随机Key造成缓存奔溃的情况,但是我们找到布隆过滤器是存在一定的误判率的,如果在Key较多的情况下可能会将不存在的Key误判为存在,并且使用布隆过滤器本身也是需要消耗一定的系统性能,当然也可以忽略这个性能损耗。

限流和验证码机制

  针对恶意攻击,例如随机生成大量无效key的请求的情况,我们还可以通过在应用层或网关层加上限流策略的方式来限制流量进入,例如可以设置单个IP或用户的请求频率。对于过于频繁的无效请求,可以引入验证码验证,确保请求来源可信,这样可以有效的防止恶意流量的进入,但是缺点就是对于正常的流量也可能会造成拦截。

  这种方式就没有具体的实现了,可以在GateWay、Nginx、Apache、Tomcat等多个服务器场景中进行设置,或者可以通过F5这些硬件方案来进行拦截。

参数校验和提前检查

  为了避免非法参数进入,我们可以通过对请求的key进行格式校验或范围校验的方式来直接拦截非法请求的key。例如在上面的例子中,对于商品ID的设置,必须是正整数且在特定范围内,如果超过了设置的返回那么Key就会之间检测返回丢弃就可以了,不需要进入到缓存中。这种做法适合于一些业务场景比较清晰明确场景,例如只有100件商品,如果ID超过100的话就可以从逻辑上进行判断,当然,这里就需要开发人员编写对应的逻辑检测代码来进行判断了。

总结

  一般在实际项目中,主要是通过缓存特殊值或者是布隆过滤器的方式来进行拦截,例如在一个用户查询系统中,我们通过布隆过滤器来拦截无效的请求,然后对为空的值做一个5分钟的短暂缓存,这样可以减少对于数据库访问的压力,当然,要说完全没有穿透是不可能的,不过在加上网关上的限流策略等方式就可以有效的避免这种问题。

  总的来说,缓存穿透可以通过多种方式解决,具体方法需要结合业务特点,比如流量模式、key 的分布等。这里我们可以通过组合多种方案的方式来防止缓存穿透,这样既能降低系统复杂度,也能更高效地应对不同场景。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/170972.html

(0)
上一篇 2025-02-21 13:45
下一篇 2025-02-21 14:05

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信