互斥锁
  缓存击穿后,多个线程会同时去查询数据库的这条数据,那么我们可以在第一个查询数据的请求上使用一个互斥锁来锁住它。
  其他的线程走到这一步拿不到锁就等着,等第一个线程查询到了数据,然后做缓存。后面的线程进来发现已经有缓存了,就直接走缓存。

static Lock reenLock = new ReentrantLock();
    public String findPubConfigByKey1(String key) throws InterruptedException {
        PubConfig result = new PubConfig();
        // 从缓存读取数据
        result = redisService.getObject(PubConfigKeyConstants.TABLE_NAME + "_"+key, PubConfig.class) ;
        if (result== null ) {
            if (reenLock.tryLock()) {
                try {
                    System.out.println("拿到锁了,从DB获取数据库后写入缓存");
                    // 从数据库查询数据
                    result = pubConfigRepository.queryPubConfigInfoByKey(key);
                    // 将查询到的数据写入缓存
                    Gson g = new Gson();
                    String value = g.toJson(result);
                    redisService.setNx(PubConfigKeyConstants.TABLE_NAME + "_"+key, value);
                } finally {
                    reenLock.unlock();// 释放锁
                }

            } else {
                // 先查一下缓存
                result = redisService.getObject(PubConfigKeyConstants.TABLE_NAME + "_"+key, PubConfig.class) ;
                if (result== null) {
                    System.out.println("我没拿到锁,缓存也没数据,先小憩一下");
                    Thread.sleep(100);// 小憩一会儿
                    return findPubConfigByKey1(key);// 重试
                }
            }
        }
        return result.getValue();
    }

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐