1.springboot集成redis
由于本例子也需要查询数据库,所以我是在上一文章的基础上去完成的.https://my.oschina.net/u/3794524/blog/1926298
1.加入springboot集成redis的依赖
<!-- springboot集成redis--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
2.在application.properties配置文件配置redis连接信息
#配置redis spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.password= spring.redis.pool.max-idle=8 spring.redis.pool.min-idle=0 spring.redis.pool.max-wait=-1 spring.redis.pool.max-active=8 spring.redis.timeout=5000
3.编写service方法和接口方法
package cn.gobon.service.impl; import cn.gobon.mapper.DepartmentMapper; import cn.gobon.pojo.Department; import cn.gobon.service.DepartmentService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; /** * @version V1.0 * @ClassName: ValidateActionJson * @Description: TODO * @Auther: Jianxiong Yi * @Date: 2018/8/11 15:13 */ @Service public class DepartmentServiceImpl implements DepartmentService { //注入mapper对象 @Autowired private DepartmentMapper departmentMapper; //注入redis模板 @Autowired private RedisTemplate<Object,Object> redisTemplate; @Override public List<Department> findAll() { return departmentMapper.findAll(); } @Transactional @Override public void update(Department department) { departmentMapper.updateByPrimaryKey(department); //抛出异常,测试事务 int i = 10 / 0; } @Override public List<Department> findAllToRedis() { //设置序列化 RedisSerializer redisSerializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(redisSerializer); //从redis中取 List<Department> departments = (List<Department>) redisTemplate.opsForValue().get("departments"); if(departments == null) { //从数据库查询 departments = departmentMapper.findAll(); //设置到redis中 redisTemplate.opsForValue().set("departments",departments); System.out.println("从mysql数据库中取......."); } return departments; } }
package cn.gobon.service; import cn.gobon.pojo.Department; import java.util.List; /** * @version V1.0 * @ClassName: ValidateActionJson * @Description: TODO * @Auther: Jianxiong Yi * @Date: 2018/8/11 15:12 */ public interface DepartmentService { //查询所有部门 List<Department> findAll(); //更新 void update(Department department); //从redis获取所有部门 List<Department> findAllToRedis(); }
4.编写Departmentcontroller方法
package cn.gobon.controller; import cn.gobon.pojo.Department; import cn.gobon.service.DepartmentService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @version V1.0 * @ClassName: ValidateActionJson * @Description: TODO * @Auther: Jianxiong Yi * @Date: 2018/8/11 15:14 */ @RestController public class DepartmentController { //注入service @Autowired private DepartmentService departmentService; @RequestMapping("/findAllDepartment") public Object findAllDepartment(){ return departmentService.findAll(); } @RequestMapping("/update") public String update(){ Department department = new Department(); department.setId(1); department.setName("保安部"); departmentService.update(department); return "success"; } @RequestMapping("/findAllToRedis") public Object departments() { return departmentService.findAllToRedis(); } }
5.启动Application.java测试
需要注意的是,实体类要实现Serializable接口
2.解决高并发穿透问题
如果在高并发同时访问该方法,会出现同时到数据库中查询的情况,这对数据库的访问压力是很大的。为了解决这个问题,我们可以使用加锁的方法去解决。以下先测试没有加锁的情况。
2.1没有加锁的情况
1.DeparmentServiceImpl(加入打印)
@Override public List<Department> findAllToRedis() { //设置序列化 RedisSerializer redisSerializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(redisSerializer); //从redis中取 List<Department> departments = (List<Department>) redisTemplate.opsForValue().get("departments"); if(departments == null) { System.out.println("从数据库中查询。。。。。"); //从数据库查询 departments = departmentMapper.findAll(); //设置到redis中 redisTemplate.opsForValue().set("departments",departments); } else { System.out.println("从redis中查询。。。。。"); } return departments; }
2. Departmentcontroller
@RequestMapping("/coucurrenceTest") public Object coucurrenceTest() { //模拟高并发 ExecutorService executorService = Executors.newFixedThreadPool(15); for (int i = 0; i < 10000; i++) { executorService.submit(new Runnable() { @Override public void run() { departmentService.findAllToRedis(); } }); } return departmentService.findAllToRedis(); }
控制台打印
2.2加锁情况
1.DepartmentServiceImpl(牺牲一点性能去避免穿透问题)
@Override public List<Department> findAllToRedis() { //设置序列化 RedisSerializer redisSerializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(redisSerializer); //从redis中取 List<Department> departments = (List<Department>) redisTemplate.opsForValue().get("departments"); if (departments == null) { //加锁 synchronized (this) { departments = (List<Department>) redisTemplate.opsForValue().get("departments"); //双重检测 if(departments == null) { System.out.println("从数据库中查询。。。。。"); //从数据库查询 departments = departmentMapper.findAll(); //设置到redis中 redisTemplate.opsForValue().set("departments", departments); } else { System.out.println("从redis中查询。。。。。"); } } } else { System.out.println("从redis中查询。。。。。"); } return departments; }
控制台打印
本人实力有限,如有错误,欢迎指点,谢谢!