Spring boot 集成 Redis 的步骤如下:
1、在pom.xml中配置相关的jar依赖:
<!-- 加载spring boot redis包 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
2、在Springboot核心配置文件application.properties中配置redis连接信息:
spring.redis.host=192.168.230.128 spring.redis.port=6379 spring.redis.password=123456
3、 配置了上面的步骤,Spring boot将自动配置RedisTemplate,在需要操作redis的类中注入redisTemplate:
redis操作的实体类必须实现序列化接口
成功后发现存入redis的key有一些特殊的编码格式,可读性不高
spring boot帮我们注入的redisTemplate类,泛型里面只能写 <String, String>、<Object, Object>
在高并发情况下,该方法可能会出现问题:可能没有缓存,都到数据库取查询,增加数据库服务器的压力。
在action中模拟多线程来访问该sevice方法
@Autowired private TClassService tClassService; @RequestMapping("index.do") public @ResponseBody Object list(){ //模拟高并发 Runnable runnable = new Runnable() { @Override public void run() { tClassService.list(); } }; ExecutorService executorService = Executors.newFixedThreadPool(10); for (int i=0;i<100;i++){ executorService.submit(runnable); } return tClassService.list(); }
修改service方法中的提示
public List<TClass> list() { RedisSerializer redisSerializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(redisSerializer); //先到缓存中查询 List<TClass> list = (List<TClass>)redisTemplate.opsForValue().get("data.class"); //如果缓存中没有数据,就从数据库取数据 if (list == null){ System.out.println("查询的数据库"); //从数据库中获取数据,查询完后将结果放入缓存 list = classMapper.list(); redisTemplate.opsForValue().set("data.class",list); }else { System.out.println("查询的缓存"); } return list; }
启动,测试结果,发下很多都是在数据库查的,而不是查询缓存
原理:多线程同时进入方法
解决方式一:同步方法
在方法上夹synchronized关键字,同步方法,效率太低
解决方式二:同步代码块
public List<TClass> list() { RedisSerializer redisSerializer = new StringRedisSerializer(); redisTemplate.setKeySerializer(redisSerializer); //先到缓存中查询 List<TClass> list = (List<TClass>)redisTemplate.opsForValue().get("data.class"); if (list == null){//如果找到了,就不加锁了,提高效率 synchronized (this){ list = (List<TClass>)redisTemplate.opsForValue().get("data.class"); //如果缓存中没有数据,就从数据库取数据 if (list == null){ System.out.println("查询的数据库"); //从数据库中获取数据,查询完后将结果放入缓存 list = classMapper.list(); redisTemplate.opsForValue().set("data.class",list); }else { System.out.println("查询的缓存"); } } }else{ System.out.println("查询的缓存"); } return list; }
测试结果,只有第一次查询数据库,其余的都是查询缓存
哨兵模式redis集群配置:
#redis集群哨兵模式配置 spring.redis.password=redis spring.redis.sentinel.master=mymaster spring.redis.sentinel.nodes=192.168.179.128:26380,192.168.179.128:26382,192.168.179.128:26384