在分布式系统中,缓存是提高性能和减轻数据库负载的常见手段之一,然而,Redis缓存中存在一些常见的问题,包括缓存穿透、击穿和雪崩。
缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库,导致数据库负载过高。攻击者可以通过恶意构造请求,频繁访问不存在的数据,从而使系统受到压力。
常见的解决方案有两种:
缓存空对象:当查询数据库返回为空时,将空结果缓存一段时间,下次查询同样的数据时直接返回缓存中的空结果。
布隆过滤器:使用布隆过滤器可以快速判断请求的数据是否存在于缓存中,如果不存在,则直接返回,避免对数据库的无效查询。
缓存空对象思路分析:
当我们客户端访问不存在的数据时,先请求redis,但是此时redis中没有数据,此时会访问到数据库,但是数据库中也没有数据,这个数据穿透了缓存,直击数据库,我们都知道数据库能够承载的并发不如redis这么高,如果大量的请求同时过来访问这种不存在的数据,这些请求就都会访问到数据库,简单的解决方案就是哪怕这个数据在数据库中也不存在,我们也把这个数据存入到redis中去,这样,下次用户过来访问这个不存在的数据,那么在redis中也能找到这个数据就不会进入到缓存了
优点:实现简单,维护方便
缺点:占用额外内存空间、缓存一致性问题(缓存与数据库的数据不一致)
布隆过滤器分析:
布隆过滤器其实采用的是哈希思想来解决这个问题,通过一个庞大的二进制数组,走哈希思想去判断当前这个要查询的这个数据是否存在,如果布隆过滤器判断存在,则放行,这个请求会去访问Redis,哪怕此时Redis中的数据过期了,但是数据库中一定存在这个数据,在数据库中查询出来这个数据后,再将其放入到Redis中,假设布隆过滤器判断这个数据不存在,则直接返回。
优点:内存占用较少,节约内存空间
缺点:实现复杂并且存在误判,误判原因是布隆过滤器走的是哈希思想,只要哈希思想,就可能存在哈希冲突。
----------------------------------------------------
缓存击穿是指当一个热点数据过期(热点Key)或被删除了,就是一个被高并发访问并且缓存重建业务较复杂的key突然失效了,大量请求同时涌入,导致数据库负载激增。这种情况下,缓存无法发挥作用,直接访问数据库可能会导致系统崩溃。
解决方案:
1. 设置热点数据过期时间(或者永不过期):对于一些热点数据,可以将其设置为永不过期,确保即使缓存失效,仍能从数据库中加载数据并重新设置缓存。
2. 加互斥锁并更新缓存:在缓存失效的瞬间,通过加锁的方式只允许一个请求访问数据库,并将查询结果更新到缓存中,其他请求等待缓存刷新。
----------------------------------------------------
缓存雪崩是指在缓存中大量的数据同时过期(key失效)或者Redis服务宕机,导致大量请求直接访问数据库,造成数据库负载过高。这种情况下,系统可能会发生故障或崩溃。
解决方案:
1. 设置缓存过期时间随机性:将缓存的过期时间设置为一个随机值,避免大量数据同时过期。
2. 使用多级缓存架构:引入多级缓存,例如本地缓存和分布式缓存,减少缓存失效的风险。
3. 缓存预热:在系统低峰期,提前加载热点数据到缓存中,避免大量请求同时访问数据库。
4. 给缓存业务添加降级限流策略