• 【分布式】缓存穿透、缓存雪崩,缓存击穿解决方案,使用锁控制缓存的加载


    原文:https://www.cnblogs.com/dream-to-pku/p/9153999.html

    static Lock reenLock = new ReentrantLock();
     
        public List<String> getData04() throws InterruptedException {
            List<String> result = new ArrayList<String>();
            // 从缓存读取数据
            result = getDataFromCache();
            if (result.isEmpty()) {
                if (reenLock.tryLock()) {
                    try {
                        System.out.println("我拿到锁了,从DB获取数据库后写入缓存");
                        // 从数据库查询数据
                        result = getDataFromDB();
                        // 将查询到的数据写入缓存
                        setDataToCache(result);
                    } finally {
                        reenLock.unlock();// 释放锁
                    }
     
                } else {
                    result = getDataFromCache();// 先查一下缓存
                    if (result.isEmpty()) {
                        System.out.println("我没拿到锁,缓存也没数据,先小憩一下");
                        Thread.sleep(100);// 小憩一会儿
                        return getData04();// 重试
                    }
                }
            }
            return result;
        }

    原文:https://my.oschina.net/u/3434392/blog/3012132

    缓存雪崩

    指的是大量缓存集中在一段时间内失效,发生大量的缓存穿透,所有的查询都落在数据库上,造成了缓存雪崩。

    解决办法

    1. 这个没有完美解决办法,但可以分析用户行为,尽量让失效时间点均匀分布,设置不同的过期时间。
    2. 用加分布式锁或者分布式队列的方式保证缓存的单线程(进程)写 (eg. redis的 SETNX),从而避免失效时大量的并发请求落到底层存储系统上。在加锁方法内先从缓存中再获取一次(防止另外的线程优先获取锁已经写入了缓存),没有再查DB写入缓存。 (当然也可以: 在没有获取锁(tryLock)的线程中一直轮询缓存,至超限时)

    缓存击穿

    指的是热点key在某个特殊的场景时间内恰好失效了,恰好有大量并发请求过来了,造成DB压力。

    解决办法

    与缓存雪崩的解决方法类似: 用加锁或者队列的方式保证缓存的单线程(进程)写,在加锁方法内先从缓存中再获取一次,没有再查DB写入缓存。 

    还有一种比较好用的(针对缓存雪崩与缓存击穿):

    物理上的缓存是不设置超时时间的(或者超时时间比较长), 但是在缓存的对象上增加一个属性来标识超时时间(此时间相对小)。 当获取到数据后,校验数据内部的标记时间,判定是否快超时了,如果是,异步发起一个线程(控制好并发)去主动更新该缓存。

    这种方式会导致一定时间内,有些请求获取缓存会拿到过期的值,看业务是否能接受而定。

  • 相关阅读:
    仪器仪表远程控制库(C++&C#)
    Opencv(EmguCV)中图像跨度stride的计算公式
    细说 Intelligent Tracking Prevention
    gRPC golang实践记录 Marathon
    golang 常用数据类型转换 Marathon
    如何在 Ubuntu 20.04 上安装 Go Marathon
    python中各数据类型的转换整型/浮点型/str型/char型/list型/dict型 Marathon
    一文了解protoc的使用 Marathon
    golang时间戳与格式化字符串的相互转化 Marathon
    常见应用的包名
  • 原文地址:https://www.cnblogs.com/shihaiming/p/11088513.html
Copyright © 2020-2023  润新知