当前位置: 首页 > 科技观察

老套的Redis雪崩、击穿、穿透、预热、降级都安排了一次_0

时间:2023-03-20 00:57:23 科技观察

关于Redis的介绍和特点,这里就不细说了,不然要千言万语。今天我们就来重点介绍一下在企业中使用Redis时的一些常见问题以及相应的解决方法。当一个请求到达业务系统,想要获取某个数据时,通常是先从缓存中获取。如果缓存中不存在,则到数据库中查询。如果找到结果,则将数据保存在缓存中,并返回结果。一项新技术的引入必然会带来一些额外的问题,那么像Redis这样优秀的NoSQL数据库又会带来什么样的问题呢?让我们等着看。CachebreakdownCachebreakdown看名字看不懂什么意思,很容易和另一个词——缓存穿透混淆。缓存击穿意味着某个键一直承载着高并发。所谓高并发就是大量的请求都是为了获取这个key对应的值。而这个key在某个时候突然过期,是不是意味着大量的请求获取不到缓存中的数据,而是去请求数据库,很可能导致数据库被压垮。这是缓存故障。既然知道了问题,该如何处理呢?这个比较简单。由于这个密钥很流行,所以不要设置过期时间。如果key的数据更新了,那么就用一个mutex来锁住它。更新。为什么要使用互斥量?如果不使用互斥锁,很容易导致数据不一致。这里,为了保证缓存和数据库的一致性,只能牺牲一点点效率。CacheAvalanche不知道各位小伙伴是哪里来的。我们有一种方言叫做“Avalanche”,意思是事情已经崩溃了。这里的RedisAvalanche好像也是这个效果。首先我们要知道什么是Redis雪崩。Redis雪崩一般称为缓存雪崩,是指在某个时间节点,大量的key失效,导致大量的请求因为无法从缓存中获取数据而请求数据库。根据上图,我们来画一下雪崩的情况是怎样的:上面黑色的部分表示缓存失效,也就是说所有的请求都需要去数据库查询数据。那么数据库的压力必然会急剧增加。如果是在一线互联网这样的超高并发场景下,数据库会直接宕机。重启也没用,因为重启之后,就会有一个巨大的流量涌入,然后会一直关机。因此,防止缓存雪崩的发生具有重要意义。缓存雪崩加随机值的方案前面已经详细介绍了什么是缓存雪崩以及它是如何发生的。如何防止缓存雪崩?很简单,因为上面说了缓存雪崩是由于某个时刻大量的节点key失效导致的问题,那么现在的问题就是如何防止大量的key在某时刻失效同一时间节点?最简单的情况就是对key的过期时间进行spread,也就是在设置key的时候给过期时间加上一个随机值,这样可以完美解决缓存雪崩的问题。但是你认为我在这里完成了吗?由于是一次性安排,我不会只告诉你解决方案。继续看缓存雪崩解决方案。很多人看到这个解决方案可能会说他们不接受。加锁不限制并发吗?加锁必然导致阻塞。如果是加锁,那么执行是这样的:流程是这样的,当多个请求同时到达业务系统时,只有一个线程可以获取到锁,然后继续在数据库中缓存或者查询数据,然后后面的过程和之前一样。执行完成后释放锁,然后其他线程竞争锁,然后重复前面的过程。这种方案的优点是可以很好的保护数据库不被挂掉,缺点是并发度极低。其实上面的方案还是可以优化的:这个是如果在缓存中拿不到,那就去串行访问数据看看,这里不一定要串行,可以配合线程池控制一定的并发数。虽然弊端很多,但也不失为一种解决方法。是否使用取决于实际业务场景。毕竟没有无用的技术方案,只有不适合业务场景的技术方案(手动狗头)。缓存穿透缓存穿透就是访问了一个不存在的key,结果发现数据库中没有这个数据,最终所有访问key的请求都是直接向数据库请求的。如果是高并发的场景,很容易把数据库搞垮。您是否注意到我们所做的一些事情是保护“弱数据库”。既然知道了问题,那么我们如何解决这个问题呢?缓存穿透解决缓存空数据什么是缓存空数据?假设某个关键数据不存在,那么就存储一个NULL。但是不要忘记设置过期时间,因为假设id=3的记录不存在,那么本次访问没有查询到任何数据,缓存中存的是null。如果过段时间新增一条3的记录,如果没有设置缓存如果设置了过期时间,则永远获取不到这条数据。缓存穿透方案Bloomfilter之Bloomfilter?这东西是什么意思?Bloomfilter是一种数据结构,更准确地说是一种概率数据结构,因为它可以判断某个Element一定不存在或者可能存在。这句话忽悠了很多人,今天硬要给大家解释一下。布隆过滤器是一个位数组,一个很长的位数组和一系列哈希函数。让我们看看下面的图片,现在让我们举个例子。假设有两个人,小强和旺财。他们经过3次hash后得到的下标分别是这样的(Bloomfilter不存储元素,它只检查某个元素是否存在做标记)小强经过上面3次hash后得到的下标分别是:2,4,5,然后数组的位置2、4、5会被置为1,就是此时的样子同理,经过上面三个hash后,王财京得到的下标分别是:3、7、11,那么数组的位置3、7、11会被设置为1,也就是当前假设是这样的来一个007,得到上面三个hash后的下标分别是:11、13、15。因为13和15的位置都是0,可以判断007一定不存在。但是现在又多了一个9527,上面三个hash后得到的下标分别是:2,5,7,但是你会发现257的三个位置都是1,那么这到底是说9527存在还是不存在呢??从我们上面的解释可以看出9527之前是不存在的,但是由于hash冲突,9527的三个下标值也刚好落在已经设置为1的下标位置,导致无法判断9527是否存在。这就是布隆过滤器的原理。你为什么不拿出一段代码?下面我们使用google包下的类来测试一下。首先需要添加依赖com.google.guavaguava30.1-jre代码为如下(详细解释我已经写在注释里了,这是实际生产中可以使用的代码)0.01%的误报率*NoExistence一定不存在*存在不一定存在*/BloomFilterbloomFilter=BloomFilter.create(Funnels.stringFunnel(Charset.forName("utf-8")),100000000,0.0001);bloomFilter.put("dead");bloomFilter.put("Knock");bloomFilter.put("Redis");System.out.println(bloomFilter.mightContain("Redis"));System.out.println(bloomFilter.mightContain("Dead"));System.out.println(bloomFilter.mightContain("Knock"));System.out.println(bloomFilter.mightContain("Java"));}}结果结束。等等……缓存穿透、预热、降级什么的你都没说。哦,我真的以为这篇文章结束了。布隆过滤器是如何解决缓存穿透问题的?既然知道了布隆过滤器的原理,那么就可以通过布隆过滤器快速判断一个key是否存在于数据库中,如果存在则去数据库中查询,如果不存在则布隆过滤器中需要去数据库再查询。缓存预热是什么鬼?如何创建缓存有这么多问题,那么为什么需要缓存呢?所谓缓存预热,就是在系统启动时,预先将一些可能会被频繁使用的数据放入缓存中,从而避免在使用时先查询数据库。这是缓存预热。名气很大,其实很简单。我在实际场景中经常使用这个缓存预热。另一种方式是添加缓存刷新页面,通过人工干预将一些可能是热点的key添加到缓存中。当流量突然增加(例如大家下班后在地铁刷手机)、服务问题(例如响应慢或无响应)或非核心服务影响核心流程的性能。保证服务仍然可用,即使它受到损害。系统可以根据一些关键数据自动降级。降级的最终目的是确保核心服务的可用性,即使它们被破坏。但是,一些业务的核心服务是不能降级的。这是一种丢掉自己的棋子而保持帅气的想法。结语关于技术的学习,除了为了应付面试而短时间记忆一些知识点外,还是建议大家在学习阶段循序渐进。孩子从出生到会走路一般还有10个月的时间,要会说话就更久了。但是这个过程是必须要有的,因为孩子需要一点一滴去适应这个未知的世界。作为成年人,我们在学习的时候也要保持这种平静的心态。有些事着急是没有用的。