Under single application cache penetrate redis solution (lock mode)

Case: Multiple threads simultaneously enter a query, the query buffer meaningless

 	@GetMapping("/details/{id}")
    @ResponseBody
    public Student getOneDetails(@PathVariable Integer id){
        for (int i = 0; i < 50; i++) {
            ExecutorService executorService= Executors.newFixedThreadPool(2);
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    selectOne(id);
                }
            });
        }
        return selectOne(id);
    }
    public Student selectOne(Integer id) {
        //redis序列化的方式
        RedisSerializer stringSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringSerializer);
        //首先从缓存中获取
        Student student= (Student) redisTemplate.opsForValue().get("studentSave");

        if(null!=student){
            log.info("redis方式");
            return student;
        }
        //缓冲中无数据,从数据库中获取,并放入redis保存
        log.info("mysql 方式");
        student= studentDao.selectOne(id);
        //磁盘的存储要求类实现序列化(Student implements Serializable)
        redisTemplate.opsForValue().set("studentSave",student);
        return student;
    }

1: The first solution: synchronized (monomer using valid)
Description: synchronized is a keyword in Java, synchronized can be used to achieve lock, the lock is released and Tim have control jvm, jvm release the lock in two cases
One is the thread executing the task, jvm release the lock, one is jvm runtime error, release the lock resources that the other thread waits

Use Cases:

	@GetMapping("/details/{id}")
    @ResponseBody
    public Student getOneDetails(@PathVariable Integer id){
        for (int i = 0; i < 50; i++) {
            ExecutorService executorService= Executors.newFixedThreadPool(2);
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    selectOne(id);
                }
            });
        }
        return selectOne(id);
    }
    public Student selectOne(Integer id) {
        //redis序列化的方式
        RedisSerializer stringSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringSerializer);
        //首先从缓存中获取
        Student student= (Student) redisTemplate.opsForValue().get("studentSave");

        if(null!=student){
            log.info("redis1方式");
            return student;
        }
        //使用synchronized使多线程实现同步查询
        synchronized (this){
            //再次判断缓存是否存在数据
            student= (Student) redisTemplate.opsForValue().get("studentSave");
            if(null!=student){
                log.info("redis2方式");
                return student;
            }
            //缓冲中无数据,从数据库中获取,并放入redis保存
            log.info("mysql1 方式");
            student= studentDao.selectOne(id);
            //磁盘的存储要求类实现序列化(Student implements Serializable)
            redisTemplate.opsForValue().set("studentSave",student);
        }
        return student;
    }

2: The second solution: lock (single use valid)

lock is an interface, Lock and release the lock requires manual operation, we can get to the target thread whether to acquire the lock, when a large number of threads simultaneously competitive, Lock's performance will be much higher than the synchronized

Use Cases:

	//定义锁
    static Lock lock=new ReentrantLock();

    @GetMapping("/details/{id}")
    @ResponseBody
    public Student getOneDetails(@PathVariable Integer id){
        new Thread(new Runnable() {
            @Override
            public void run() {
                selectOne(id);
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                selectOne(id);
            }
        }).start();
        return selectOne(id);
    }
    public Student selectOne(Integer id) {
        //redis序列化的方式
        RedisSerializer stringSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringSerializer);
        //首先从缓存中获取
        Student student= (Student) redisTemplate.opsForValue().get("studentSave");
        if(null!=student){
            log.info("redis1方式");
            return student;
        }

        lock.lock();
        try {
            //需要同步的代码片段
            if(lock.tryLock()){
                //再次判断缓存是否存在数据
                student= (Student) redisTemplate.opsForValue().get("studentSave");
                if(null!=student){
                    log.info("redis2方式");
                    return student;
                }
                //缓冲中无数据,从数据库中获取,并放入redis保存
                log.info("mysql1方式");
                student= studentDao.selectOne(id);
                //磁盘的存储要求类实现序列化(Student implements Serializable)
                redisTemplate.opsForValue().set("studentSave",student);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //释放锁资源
            lock.unlock();
        }
        return student;
    }
Published 27 original articles · won praise 1 · views 839

Guess you like

Origin blog.csdn.net/weixin_44971379/article/details/105182280