springboot- 集成redis实现高并发缓存(二)使用同步锁和双重检测法解决高并发下的缓存穿透问题

1.  在高并发的时候,这个程序存在缓存穿透的问题

假如有1万人进来,有200人都同时查询不到数据库,所以要进行200次数据库查询。合理的情况应该有一个人进来查询数据,把数据放到缓存里,剩下的9999人从redis取数据

解决办法:使用同步锁和双重检测法

/**注入springboot自动配置的redisTemplate**/
    //打卡排行榜
    public  List getCheckRank(){

        //字符串的序列化器
        RedisSerializer redisSerializer=new StringRedisSerializer();
        redisTemplate.setKeySerializer(redisSerializer);

        //查询缓存
        List rankList=(List) redisTemplate.opsForValue().get("checkRank");
        //双重检测锁
        if(null==rankList) {
            synchronized (this) {
                //从redis获取一下
                rankList = (List) redisTemplate.opsForValue().get("checkRank");
                if (null == rankList) {
                    //缓存为空,查询一遍数据库
                    rankList = weightMapper.getCheckRank();
                    //把数据库查询出来的数据,放入redis中
                    redisTemplate.opsForValue().set("checkRank", rankList);

                }
            }
        }
       
        return  rankList;
    }

2. 使用多线程验证

在controller里添加以下代码进行测试,一般线程池的个数根据cpu数取值,一个cpu可以创建两个线程池。

  @ResponseBody
    @GetMapping("/checkRankTest")
    public Object checkRankTest() {


        Runnable runnable=new Runnable() {
            @Override
            public void run() {
                weightService.getCheckRank();

            }
        };
        //创建25个线程池,起10000个线程提交
        ExecutorService executorService= Executors.newFixedThreadPool(25);
        for(int n=0;n<100000;n++)
        {
            executorService.submit(runnable);
        }
        return weightService.getCheckRank();

    }

 3. 运行结果:只运行了一次mysql查询,其他都是从redis访问获得

springboot- 集成redis实现高并发缓存(二)使用同步锁和双重检测法解决高并发下的缓存穿透问题_第1张图片

你可能感兴趣的:(springboot,redis)