博客主页:🏆看看是李XX还是李歘歘 🏆

🌺每天不定期分享一些包括但不限于计算机基础、算法、后端开发相关的知识点,以及职场小菜鸡的生活。🌺

💗点关注不迷路,总有一些📖知识点📖是你想要的💗

⛽️今天的内容是      Redis雪崩、穿透、击穿      ⛽️💻💻💻

Redis雪崩、穿透、击穿_数据库

首先来讨论一下Redis的过期键的删除策略有哪些?

  • 定时过期每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。
  • 惰性过期:只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。
  • 定期删除每隔一定的时间,会扫描redis数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果

内存淘汰算法请参考:Redis的内存淘汰算法

数据读取流程 

  1. 如果我们的数据在缓存里边有,那么就直接取缓存的。
  2. 如果缓存里没有我们想要的数据,我们会先去查询数据库,然后将数据库查出来的数据写到缓存中

为什么使用redis?

  1. 提高性能:缓存査询速度比数据库查询速度快(内存Vs硬盘);
  2. 提高井发能力:缓存分担了部分请求,支持更高的并发。

雪崩

内存昂贵且有限,所以Redis需要给数据设置过期时间,将过期键数据删除。

雪崩即是指在某一个时间段,缓存集中过期失效

例如:缓存数据设置的过期时间是相同的,并且Redis恰好将这部分数据全部删光了。这就会导致在这段时间内,这些缓存同时失效,全部请求到数据库中。

解决方案

同一时间段内 ,缓存过期

在缓存的时候给过期时间加上一个随机值,这样就会大幅度的减少缓存在同一时间过期。

Redis挂掉了

事发前:实现Redis的高可用(主从架构+Sentinel(哨兵) 或者Redis Cluster(集群)),尽量避免Redis挂掉这种情况发生

事发中:万一Redis真的挂了,我们可以设置本地缓存(ehcache)+限流(hystrix),尽量避免我们的数据库被干掉(起码能保证我们的服务还是能正常工作的)

事发后:redis持久化,重启后自动从磁盘上加载数据,快速恢复缓存数据

穿透

请求的数据在缓存大量不命中(指查询一个一定不存在的数据),导致请求走数据库。

例如,请求数据库ID为负数。

解决方案

布隆过滤器(BloomFilter)或者压缩filter提前拦截,不合法就不让这个请求到数据库层

布隆过滤器(BloomFilter)原理和实现

当我们从数据库找不到的时候,我们也将这个空对象设置到缓存里边去。下次再请求的时候,就可以从缓存里边获取了。这种情况我们一般会将空对象设置一个较短的过期时间(时间太长的话,万一数据库中已经有数据了,但是长时间命中redis发现没有数据,导致用户拿不到数据)。

击穿

击穿即大量请求单个key,但是这个key突然失效,导致大量请求穿过缓存访问到数据库。

例如:redis缓存中有一个key是大量请求同时访问的热点数据,如果突然这个key过期了,那么大量的请求在缓存中获取不到该key,穿过缓存直接来到数据库导致数据库崩溃。

解决方案

  • 热点key不设置过期时间,即key一直存在于缓存中,更新时直接覆盖即可。
  • 使用基于 redis or zookeeper 互斥锁的方案,在缓存中没有数据去数据库查询时加上锁,让一个线程去查询数据库以及更新缓存,其他线程等待,这样减小数据库压力。
  • 热点Key进行限流
  • 将热 key 分散到不同的服务器中


Redis雪崩、穿透、击穿_数据_02