Redis 缓存优化:缓存雪崩、缓存击穿、缓存穿透的概念与预防

文章目录

    • 缓存雪崩
    • 缓存击穿
    • 缓存穿透

在实际的业务场景中,Redis 通常作为缓存和其他数据库(例如 MySQL)搭配使用,用来减轻数据库的压力。但是在使用 Redis 作为缓存数据库的过程中,可能会遇到一些常见问题,例如缓存穿透、缓存击穿和缓存雪崩等。

缓存雪崩

缓存雪崩是指缓存中大批量的 key 同时过期,于是大量请求访问数据库,从而导致数据库压力激增,甚至引起数据库宕机,这种现象被称为 “缓存雪崩”。

避免缓存雪崩的措施有:

  1. 给缓存数据设置不同的过期时间,避免同时过期;
  2. 利用 Redis 集群提高服务可用性,避免因 Redis 宕机引起的缓存雪崩;
  3. 给缓存业务添加降级限流策略;
  4. 使用多级缓存架构,分散缓存失效的影响。

缓存击穿

如果 Redis 中一个被高并发访问并且缓存重建业务较复杂的 Key 突然失效,那么大量请求将直接访问数据库,从而瞬间给数据库造成巨大冲击。这种现象被称为 “缓存击穿”。

避免缓存击穿的措施有:

  1. 使用互斥锁:

    当缓存未命中时,通过互斥锁方式,确保只有一个线程访问后端存储获取数据,并重建缓存,其他线程保持排队等待。

    优点:没有额外内存消耗(不需要设置逻辑过期数据);保证数据库数据与缓存数据的一致性;

    缺点:线程需要等待,性能受影响;当多个线程需要竞争多把锁时,可能会有死锁风险。

  2. 逻辑过期:将缓存设置一个逻辑过期时间,线程每次都会访问到缓存。当取到过期数据时,开启一个新线程,用于缓存重建,同时需要给新线程加上互斥锁(用于保证单个缓存的重建只被一次执行)。

    优点:线程无需等待,性能较好;

    缺点:不保证数据库数据与缓存数据的一致性;有额外内存消耗。

缓存穿透

当用户查询某个数据时,Redis 中不存在该数据,即未命中缓存,所以此时查询数据的请求将访问持久层数据库(例如 MySQL 数据库)以获取需要的数据,但是发现数据库中也并不存在该数据,于是数据库将返回空对象。此类请求如果过多,或者恶意用户利用此漏洞进行恶意攻击,将会给数据库造成过大压力,甚至引起数据库崩溃。这种现象被称为 “缓存穿透”。

避免缓存穿透的措施有:

  1. 缓存空值:

    当请求未命中缓存,同时数据库中也无法查询到数据时,直接将请求对应的数据在 Redis 中缓存为空值。当请求再次访问该数据时,Redis 将直接返回缓存中缓存的空值,从而使请求避免直接访问数据库。

    该方案也有缺点:

    • 额外内存消耗:因为 Redis 是基于内存的,所以将产生额外的内存消耗。
    • 数据不一致:在实际开发中,通常在更新数据库数据时同步删除缓存,以达到缓存与数据库数据一致的目的。但是在更新数据成功后到更新缓存成功前的极短时间内,可能会造成极短时间的缓存与数据库数据的不一致。

    针对上述两个问题,可以设置一个较短的 TTL(缓存过期时间)以规避。

  2. 使用布隆过滤器:

    布隆过滤器的特性之一是可以判定数据是否存在,布隆过滤器的这一特性可以用于解决缓存穿透问题。通过布隆过滤器可以将无效请求过滤掉,以确保合法的请求才能访问后端数据库。

    当有一个用户请求到来时会先经过布隆过滤器,如果请求的数据,布隆过滤器中不存在,那么该请求将直接被拒绝,否则将继续执行查询。

    Redis 缓存优化:缓存雪崩、缓存击穿、缓存穿透的概念与预防_第1张图片

    相较于第一种方法,布隆过滤器内存占用较少,更为高效、实用,但是存在误判可能。

另外,对于恶意用户进行的恶意攻击而导致的缓存穿透情况,也可以通过限流、黑名单等手段加以限制,从而保护后端数据库免受恶意攻击。

你可能感兴趣的:(Redis,缓存,redis,数据库)