Redis 击穿、穿透、雪崩

Redis 击穿、穿透、雪崩

业务场景:做缓存使用时
数据缓存在redis中,过滤大部分请求,实现只有少量请求达到数据库服务。给数据库减轻压力

击穿

  • 原因

    • 给key设置了过期时间(LRU/LFU)
    • 当key过期之后,数据被清理掉了。突然来了一批访问这个Key的。这是请求就会压到数据库上
    • Key的过期导致的高并发访问数据库,给数据库造成了压力
    • 如果过期之后,只有少量请求访问这个Key,达到数据库不能成为击穿。只有出现高并发的时候,对数据库产生影响了才叫击穿
  • 解决方案

    • 有并发时,阻止并发到达数据库,但是redis中又没有key

    • redis是单进程单实例的,让访问的请求当发现key不存在的时候,使用setnx()创建一个key ,相当于向redis申请一把锁。因为setnx()只有没有这个key时,才会返回成功。所以一定只有一个请求能获得这把锁。只有获得锁的请求才允许访问数据库

    • 1.取key,发现没有key

    • 2.使用setnx()设置Key,相当于申请锁

      • 失败的,睡眠一会,苏醒之后重复1-2步。
        如果第一步成功就能直接返回了,如果第一步失败,再次尝试setnx(),因为锁还存在,所以依然不能成功,继续进入睡眠
      • 设置key成功的请求访问数据库
    • 存在的问题

      • 死锁了,获得锁的线程挂掉了怎么办

        • 设置锁的过期时间
        • 当第一个挂掉后,锁过期了,会有其他的请求拿到锁。去访问数据库
      • 获得锁的线程没挂,但是阻塞了,因为设置的锁过期时间不够。第一个获得获得还没有取回数据,锁就被释放了,就会导致多个请求到达数据库、可能会导致部分请求延迟,丢失。
        第一个从数据库获取到数据,返回了,没有获取到锁的,苏醒之后取到Key返回了
        而其他获取到锁的请求,还在阻塞

      • 解决方案

        • 多线程,开启一个守护线程

          • 代码逻辑复杂度会提高一些
        • 第一个请求获取到锁之后,一个线程去数据库取数据,另一个线程监控值是不是取回来了,如果没有取回来,就更新锁时间

穿透

  • 业务场景:做缓存使用时

  • 原因

    • 请求了系统中不存在的数据,自然在redis中查找不到key,从而请求达到数据库,进行数据库查询
  • 解决方案

    • 使用布隆过滤器,三种方式

      • 在客户端实现布隆的算法,和存储数据
        则请求不到达redis,和数据库
      • 在客户端中实现布隆过滤器的算法,数据存储在redis中。
      • redis集成布隆过滤器
    • 缺点:布隆过滤器只能增加,不能删除

      • 当业务数据会出现删除,修改的时候。使用布隆过滤器会出现问题
      • 替代方案:布谷鸟过滤器

雪崩

  • 业务场景:做缓存使用时

  • 原因

    • 和击穿比较像,同一时间大量的key值过期
      例如:晚上12点大量的Key需要进行更新。
      导致这些key的请求如果在这时发生,则会出现大量的请求到达数据库。
  • 解决方案

    • 当业务层面数据必须在同一时间大量进行更新时

      • 强依赖击穿方案,让请求进行排队。只让少量的请求达到数据库
      • 定时更新,如果大部分的数据都需要在12点进行更新时,则每晚11:50至12:10分让业务暂停使用。时间可以根据时间情况控制
    • 当业务层面对数据更新时间没有要求时

      • Key值过期时间均匀分布
        -在这里插入图片描述