发布时间:2025-11-05 11:53:06 来源:云智核 作者:数据库

「Redis 是存穿存击穿缓存雪一个开源(BSD许可)的,内存中的透缓数据结构存储系统,它可以用作数据库、崩吊缓存和消息中间件。打面」
Redis在缓存应用中还是试官很广泛的,项目中也经常使用。看完基本上面试中肯定都会问到,存穿存击穿缓存雪总结一下增强记忆哈!透缓
在享受缓存带来的崩吊好处的同时,当然要防止这些不好的打面方面。
下面我们一起来看看这三种情况的试官产生原因和解决方案!
「总结: 这三种情况都是看完在大量请求来的时候,Redis没有命中,存穿存击穿缓存雪请求直接打到数据库,透缓从而导致数据库挂掉!」
Redis缓存简图:

「大量请求的 key 是不合理的,缓存中根本不存在(数据库中一般也不存在),高防服务器导致这些请求绕过缓存直接访问数据库,给数据库造成了巨大的压力,随时可能宕机。」
恶意查询,如查询id为负数等等。key过期,突然来了大量请求时。key没有提前预热,突然来了大量请求时。redis有一个配置,可以把从数据库查询出来为空的也缓存到Redis中,也可以自己在代码中写,顺便加上过期时间,也可以配置过期时间,这样是全局都是这个过期时间了,b2b供应网不太建议这样!
复制spring: cache: redis: cache-null-value: true time-to-live: 30s1.2.3.4.5. 「限制并发查询:」@Cacheable(value={"category"},key = "#root.methodName",sync = true)
❝
sync = true:表示多个线程在尝试获取缓存数据的时候会被阻塞,直到第一个线程从数据库加载数据并放入缓存后,其他线程才能获取到缓存中的数据。这样可以避免多个线程同时查询底层数据库,减轻数据库负载,但会降低并发性能。 默认为false,不开启
❞
「布隆过滤器:」布隆过滤器(Bloom Filter)是一种用于判断一个元素是否属于一个集合的数据结构。它的主要特点是高效地判断元素是否存在于集合中,且具有空间和时间效率高的优点。布隆过滤器不会存储实际的数据,而是通过一系列的哈希函数和位数组来判断元素的存在。

「当布隆过滤器判断元素不存在时,元素一定不存在,元素存在时,元素不一定存在!」
是不是有点绕,云南idc服务商我们在详细说一下:
布隆过滤器有一定的假阳性概率,即在判断元素存在时,有可能出现错误的结果。这是因为多个元素可能产生相同的哈希值,导致位数组中的位被设置为1。
「布隆过滤器一旦添加了元素,就不能删除,因为删除元素会影响其他元素的判断结果。」
一般引入guava中的BloomFilter来实现布隆过滤器!如果喜欢用Hutool,也是有实现的!
下面小编给大家简单的写个demo,大家感受一下!
「引入依赖」 复制<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>30.1-jre</version> </dependency>1.2.3.4.5. 「配置布隆过滤器」 复制/** * @author wangzhenjun * @date 2023/11/7 17:08 */ @Configuration public class BloomFilterConfig { // 预期插入的元素个数,从配置文件里拿 private static final Integer EXPECTED_INSERTIONS = 100000; // 期望的误判率,值越低,布隆过滤器计算时间越长,从配置文件里拿 private static final Double FPP = 0.03; @Bean public BloomFilter<String> bloomFilter(){ BloomFilter<String> filter = BloomFilter.create(Funnels.stringFunnel(Charset.forName("utf-8")), EXPECTED_INSERTIONS,FPP); return filter; } }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20. 「简单测试」为了简单,直接写在启动类上了,大家不要学哈!
复制@EnableAsync @MapperScan("com.example.demonew.demo.mapper") @EnableTransactionManagement @SpringBootApplication public class DemoNewApplication { @Autowired private BloomFilter bloomFilter; public static void main(String[] args) { SpringApplication.run(DemoNewApplication.class, args); } @PostConstruct public void init(){ bloomFilter.put("123"); boolean b = bloomFilter.mightContain("123"); System.out.println("是否存在:" + b); } }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.
「缓存击穿是指当缓存中某个热点key刚刚过期(一般和缓存穿透区别在于热点数据存在于数据库中),在热点数据重新放入缓存之前,瞬间大量的请求绕过缓存,直接打到数据库,数据库随时宕机!」
并发访问热点key:多个并发请求同时访问相同的缓存键
缓存策略问题:设置了过于短的缓存过期时间,容易导致缓存频繁失效。
「一般出现在秒杀中,秒杀都会提前预热,设置key直到活动结束才会过期!」
在项目启动时,或者定时任务扫描进行预热!
「限制并发查询:」@Cacheable(value={"category"},key = "#root.methodName",sync = true)、
详细解释上面已经说过了哈!
「接口限流、熔断、降级」可以引入:Sentinel来帮助我们更好的限流、熔断、降级,这里就不详细演示了!
其实缓存击穿和缓存雪崩是很相似的,解决方案,大家也可以看出来很多相同的!这就引出下一个经常问到的问题:
关于Redis的哨兵搭建可以看一下之前写的文章,这里就不演示了!
关于多级缓存,可以引入本地缓存Caffeine。
缓存击穿是缓存中某个热点key不存在了,缓存雪崩是缓存中大量或者所有key都不存在了
他俩的根本区别在于一个是单个key,一个是多个甚至全部key!
这里补充一下,关于缓存污染的吧!
缓存污染指缓存中一些访问次数很少的key,甚至只有一次!但是缓存中会存储着,占用内存空间。随着时间越来越久,内存很快被占满,就需要开启淘汰策略去额外处理这些多余的key,影响redis性能。
最主要还是要把不常用的key找到,后面不在加入缓存,从根本上解决!
还会出现在多个节点之间的数据同步出现数据不统一时产生,这个东西不好避免,因为Redis 是AP(可用性和分区容忍性),在多节点时,一半以上同步完成时,就认为同步成功了!
引入了缓存就必须要保持缓存的一致性,不然加了缓存没有任何意义!
网上关于缓存一致性的文章很多,什么延迟双删等等。
这些都不如阿里Canal,这个是通过监听MySQL的Bin Log日志,来去更新到缓存中!
今天我们深入具体的讨论了Redis缓存穿透、缓存击穿、缓存雪崩的产生原因和解决方案,补充了缓存污染和缓存一致性。
是不是有了深刻的印象,这些东西在企业级还是挺常见的,在面试过程中更加常见。 相信大家从头看到尾,对于面试肯定是没有任何问题的。
在企业级应用中,一定要具体情况具体分析,不要盲目照搬,不一定适合你们的需求。
随便看看