一.当采用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 }
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 }
二.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 }
三.源码地址
https://github.com/liushaoye/02-transaction/tree/reddis
原文地址:https://www.cnblogs.com/liuyangfirst/p/9279925.html
时间: 2024-10-04 15:44:33