详解缓存雪崩,缓存穿透,缓存击穿及其解决方案

一、正常情况

正常情况下的流程是这样的,先查缓存,缓存无就查数据库。

二、缓存雪崩

缓存雪崩是指缓存中的数据大批量的过期 ,而查询量巨大,造成数据库压力过大而崩溃。

1、解决方法

  • 尽量保证redis集群的高可用性,当发现机器坠机时尽快补上。
  • 选择合适的缓存淘汰策略。
  • 缓存的过期设置随机时间,防止大量数据同时过期。
  • 利用redis持久化机制保存的数据尽快恢复缓存。

三、缓存击穿

缓存击穿是指缓存中没有数据,而数据库中有数据,一般是缓存中的数据过期了,然后很多用户并发查询该数据,同时在缓存中读取该数据没读取到,就同时去数据库中查,造成数据库压力过大。缓存击穿强调的是一个数据过期,同时并发去访问该数据;而缓存雪崩是强调大量的数据过期。

1、解决方法

  • 设置热点数据永不过期。
  • 加互斥锁。
    互斥锁示例如下:
    /**
     * @Description: 使用互斥锁来获取数据
     * @Author: caixucheng
     * @Date: 2020/10/6 20:12
     * @param key: key
     * @return: java.lang.Object
     * @version: v1.0.0
     **/
    public Object getData(String key) throws InterruptedException {
    
    
        // 从缓存中获取key
        Object res = getDataFormRedis;
        if (res == null){
    
    
            // 缓存中没有
            // 尝试去获取锁
            if (reentrantLock.tryLock()){
    
    
                // 去数据库中查
                res = getDataFormSql(key);
                if (res != null){
    
    
                    // 写进缓存
                    updateDataRedis(key,res);
                    // 释放锁
                    reentrantLock.unlock();
                }
            }else {
    
    
                // 暂停100ms再去获得锁
                Thread.sleep(100);
                res = getData(key);
            }

        }

        return res;
    }

四、缓存穿透

缓存穿透是指缓存中没有该数据,数据库中也没有该数据。而用户不断地发请求,比如不断发生一些id=-1或者是根本就很不合理的数据来发生请求。这种一般是别人想攻击你。攻击会导致数据库压力过大。

大概流程变为如下:
在这里插入图片描述

1、解决方法

  • 做好参数检验,对于一些不合理的数据判断后直接返回。
  • 缓存无效key,当从缓存和数据库中都查不到某个key的数据,就将这个key写入缓存并设置过期时间。
  • 使用布隆过滤器。当请求进来后,先用布隆过滤器判断当前请求的数据是否在布隆过滤器中,如果没有则返回,有则去向下请求缓存,缓存没有就去请求数据库。关于布隆过滤器可以看此文章:详解布隆过滤器,并教你自己实现一个布隆过滤器

猜你喜欢

转载自blog.csdn.net/qq_14810195/article/details/108943283