IntelliJ IDEA 2017版 spring-boot2.0.4+mybatis+Redis处理高并发,穿透问题

一.当采用reddis缓存的时候,如果同时,一万次访问,那么就会有10000次访问数据库所以就会对数据库造成巨大压力,这时候,就要用到线程

    1.方法体上加锁(优点,防护住了并发锁,缺点降低了内存效率)

 1  /**
 2      * 最简洁的高并发处理,但是,牺牲效率大
 3      *
 4      * @return
 5      */
 6     public synchronized List<Student> selectAllStudent1() {
 7 
 8         // 字符串序列化器
 9         RedisSerializer redisSerializer = new StringRedisSerializer();
10         redisTemplate.setKeySerializer(redisSerializer);
11 
12         /**
13          * 在高并发条件下,此处有问题,缓存穿透问题
14          */
15         //查询关键字
16         List<Student> studentList = (List<Student>) redisTemplate.opsForValue().get("allStudents");
17 
18         if (null == studentList) {
19 
20             //缓存为空,查询数据库
21             studentList = studentMapper.selectAllStudent();
22 
23             //把数据库中查询出的数据,放入redis中
24             redisTemplate.opsForValue().set("allStudents", studentList);
25         }
26 
27         return studentList;
28     }
View Code

    2.加双锁

 1 /**
 2      * 双锁的提高效率版本
 3      *
 4      * @return
 5      */
 6     @Override
 7     public List<Student> selectAllStudent() {
 8 
 9         // 字符串序列化器
10         RedisSerializer redisSerializer = new StringRedisSerializer();
11         redisTemplate.setKeySerializer(redisSerializer);
12 
13         /**
14          * 在高并发条件下,此处有问题,缓存穿透问题
15          */
16         //查询关键字
17         List<Student> studentList = (List<Student>) redisTemplate.opsForValue().get("allStudents");
18 
19         if (null == studentList) {
20             //因为spring中的对象都是单例模式的,所以,直接对对象加锁
21             synchronized (this) {
22                 // 从redis获取一下
23                 studentList = (List<Student>) redisTemplate.opsForValue().get("allStudents");
24                 if (null == studentList) {
25                     System.out.println("查询数据库*******************");
26                     //缓存为空,查询数据库
27                     studentList = studentMapper.selectAllStudent();
28 
29                     //把数据库中查询出的数据,放入redis中
30                     redisTemplate.opsForValue().set("allStudents", studentList);
31                 } else {
32                     System.out.println("查询缓存*******************");
33                 }
34             }
35         } else {
36             System.out.println("查询缓存*******************");
37         }
38 
39         return studentList;
40     }
View Code

二.Controller中加线程池进行效验

 1 /**
 2      * Redis测试,完善好的高并发
 3      *
 4      * @return
 5      */
 6     @GetMapping("/student/selectAllStudent")
 7     public Object selectAllStudent() {
 8 
 9         //线程,该线程,调用底层查询所有学生方法
10         Runnable runnable = new Runnable() {
11             @Override
12             public void run() {
13                 studentService.selectAllStudent();
14             }
15         };
16 
17 
18         //多线程测试穿透问题
19         ExecutorService executorService = Executors.newFixedThreadPool(25);
20 
21         for (int i = 0; i < 10000; i++) {
22             executorService.submit(runnable);
23         }
24 
25         return studentService.selectAllStudent();
26     }
View Code

三.源码地址

https://github.com/liushaoye/02-transaction/tree/reddis

猜你喜欢

转载自www.cnblogs.com/liuyangfirst/p/9279925.html