缓存穿透、击穿、雪崩的解决方法

一、缓存穿透指的是查询一个不存在的数据,由于缓存中没有对应的值,每次请求都要查询数据库,容易导致数据库压力过大。

解决方法:

  1. 使用布隆过滤器等手段可以在请求到达后台处理之前就过滤掉这些不存在的请求,避免了对数据库的访问。例如在给定的场景中,布隆过滤器用于检查数据是否存在,如果不存在则直接返回错误信息,而不需要在访问数据库。
  2. 将查询为空的 key 也缓存起来,但是设置一个较短的过期时间,防止缓存层被大量无效请求填满。
  3. 在应用层对请求参数进行校验,过滤掉无效的请求。

二、缓存击穿指的是一个热点数据失效后,大量并发请求同时访问数据库,导致数据库压力过大。

解决方法:

  1. 在缓存失效时,使用互斥锁或分布式锁来保护后端系统的访问,只允许一个线程去查询数据库,其他线程等待查询结果,避免了大量并发请求穿透到后端系统。
  2. 可以使用热点数据预加载或预热缓存,在即将过期的缓存数据失效前提前重新加载,避免热点数据因缓存失效而引发击穿问题。

例如,redis在高并发下,为了避免请求直接打到数据库,可以使用双重检查锁的方式进行数据库查询。不设置双重检查的话,那在第一个获取锁的线程同步数据库到Redis期间堆积的所有线程都会在获取锁后查询数据库并设置缓存。具体步骤如下:

  1. 先查 redis 中是否有数据
  2. 如果 redis 中没有数据,使用 synchronized 进行加锁
  3. 再次查询 redis 中是否有数据
  4. 如果第3步查询还是没有数据,此时再查数据库
  5. 查询到数据库中的数据后,将数据写入到redis中。

代码示例:

java 复制代码
    public String getDataFromDatabase(String key) {
        // 先查 Redis 中是否有数据
        String data = jedis.get(key);

        // 第一重检查,如果 Redis 中有数据,直接返回
        if (data != null) {
            return data;
        }
        // 使用双重检查锁的方式避免多线程同时查询数据库
        if (lock.tryLock()) {
            try {
                // 第二重检查,再次查询 Redis 中是否有数据
                data = jedis.get(key);
                if (data != null) {
                    return data;
                }
                // 模拟从数据库中查询数据
                data = fetchDataFromDatabase(key);
                // 将查询到的数据写入 Redis 中
                jedis.set(key, data);
            } finally {
                // 释放锁
                lock.unlock();
            }
        }
        return data;
    }

三、缓存雪崩指的是缓存中的大量数据同时失效,导致大量请求直接访问数据库,造成数据库瞬时压力过大。

解决方法:

  1. 给缓存数据设置随机的过期时间,避免大量缓存同时失效。
  2. 使用多级缓存架构,如主从复制、分布式缓存等,减少单点故障风险。
  3. 引入熔断机制或限流策略,当缓存层面发生雪崩时,限制对后端系统的请求,保护后端系统免受过载。
相关推荐
Raink老师7 小时前
【AI面试临阵磨枪-79】实时数据 RAG:订单、商家、物流、天气、动态库存
人工智能·面试·职场和发展
Cosolar8 小时前
Chroma向量库面试学习指南
数据库·人工智能·面试·职场和发展·数据库架构
小江的记录本9 小时前
【JVM虚拟机】垃圾回收GC:垃圾收集器:CMS:核心原理、回收流程、优缺点、废弃原因(附《思维导图》+《面试高频考点清单》)
java·jvm·后端·python·spring·面试·maven
cfm_29149 小时前
Redis数据安全性解析
数据库·redis·缓存
无小道11 小时前
Redis——集合类型相关命令
redis·set
辞忧九千七11 小时前
Redis 单机一主二从主从复制完整搭建指南
数据库·redis·缓存
小江的记录本11 小时前
【JVM虚拟机】垃圾回收GC:垃圾回收算法:标记-清除、标记-复制、标记-整理、分代收集(附《思维导图》+《面试高频考点清单》)
java·jvm·后端·python·算法·安全·面试
小江的记录本12 小时前
【JVM虚拟机】垃圾回收GC:垃圾收集器:G1:Region分区、Mixed GC、回收流程、适用场景(高频)(附《思维导图》+《面试高频考点清单》)
java·jvm·后端·python·spring·spring cloud·面试
Chasing__Dreams12 小时前
Redis--基础知识点--32--redis底层存储结构
数据库·redis·缓存
野生技术架构师13 小时前
我有个大胆的想法,用 PostgreSQL 代替 Redis
数据库·redis·postgresql