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

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

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

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

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

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

        //查询缓存
        List<Rank> rankList=(List<Rank>) redisTemplate.opsForValue().get("checkRank");
        //双重检测锁
        if(null==rankList) {
            synchronized (this) {
                //从redis获取一下
                rankList = (List<Rank>) 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访问获得

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值