`
哈哈哈558
  • 浏览: 14671 次
社区版块
存档分类
最新评论

Spring Boot : Redis缓存使用姿势盘点

 
阅读更多

1. Redis 简介

Redis 是目前业界使用最广泛的内存数据存储。相比 Memcached,Redis 支持更丰富的数据结构,例如 hashes, lists, sets 等,同时支持数据持久化。除此之外,Redis 还提供一些类数据库的特性,比如事务,HA,主从库。可以说 Redis 兼具了缓存系统和数据库的一些特性,因此有着丰富的应用场景。本文介绍 Redis 在 Spring Boot 中两个典型的应用场景。

2. Lettuce 简介

如果在 Java 应用中使用过 Redis 缓存,那么对 Jedis 一定不陌生, Lettuce 和 Jedis 一样,都是连接 Redis Server 的客户端程序。Jedis 在实现上是直连 Redis Server,多线程环境下非线程安全,除非使用连接池,为每个 Jedis 实例增加物理连接。 Lettuce 基于 Netty 的连接实例(StatefulRedisConnection),可以在多个线程间并发访问,且线程安全,满足多线程环境下的并发访问,同时它是可伸缩的设计,一个连接实例不够的情况也可以按需增加连接实例。(了解源码可+求求: 1791743380)

3. Spring Boot 应用中使用方式

  • 直接通过 RedisTemplate 来使用
  • 使用 Spring Cache 集成 Redis
  • 通过 Spring Session 做 Session 共享

4. 工程实战

4.1 工程依赖 pom.xml 如下:

代码清单:spring-boot-redis/pom.xmlc

Java代码 
  1. <dependencies>  
  2.     <dependency>  
  3.         <groupId>org.springframework.boot</groupId>  
  4.         <artifactId>spring-boot-starter-data-redis</artifactId>  
  5.     </dependency>  
  6.     <dependency>  
  7.         <groupId>org.apache.commons</groupId>  
  8.         <artifactId>commons-pool2</artifactId>  
  9.     </dependency>  
  10.     <dependency>  
  11.         <groupId>org.springframework.boot</groupId>  
  12.         <artifactId>spring-boot-starter-web</artifactId>  
  13.     </dependency>  
  14.     <dependency>  
  15.         <groupId>org.springframework.session</groupId>  
  16.         <artifactId>spring-session-data-redis</artifactId>  
  17.     </dependency>  
  18.   
  19.     <dependency>  
  20.         <groupId>org.projectlombok</groupId>  
  21.         <artifactId>lombok</artifactId>  
  22.         <optional>true</optional>  
  23.     </dependency>  
  24.     <dependency>  
  25.         <groupId>org.springframework.boot</groupId>  
  26.         <artifactId>spring-boot-starter-test</artifactId>  
  27.         <scope>test</scope>  
  28.     </dependency>  
  29. </dependencies>  

 

  • spring-boot-starter-data-redis :在 Spring Boot 2.x 后底层不再是使用 Jedis ,而是换成了 Lettuce ,如图:

  • commons-pool2 : 用作 redis 连接池,如不引入启动会报错。

  • spring-session-data-redis : Spring Session 引入,用作共享 Session 。

  • 4.2 配置文件 application.yml

代码清单:spring-boot-redis/src/main/resources/application.yml

Java代码 
  1. server:  
  2.   port: 8080  
  3.   servlet:  
  4.     session:  
  5.       timeout: 30m  
  6. spring:  
  7.   application:  
  8.     name: spring-boot-redis  
  9.   cache:  
  10.     # 使用了Spring Cache后,能指定spring.cache.type就手动指定一下,虽然它会自动去适配已有Cache的依赖,但先后顺序会对Redis使用有影响(JCache -> EhCache -> Redis -> Guava)  
  11.     type: REDIS  
  12.   redis:  
  13.     host: 192.168.0.128  
  14.     port: 6379  
  15.     password: 123456  
  16.     # 连接超时时间(ms)  
  17.     timeout: 10000  
  18.     # Redis默认情况下有16个分片,这里配置具体使用的分片,默认是0  
  19.     database: 0  
  20.     lettuce:  
  21.       pool:  
  22.         # 连接池最大连接数(使用负值表示没有限制) 默认 8  
  23.         max-active: 100  
  24.         # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1  
  25.         max-wait: -1  
  26.         # 连接池中的最大空闲连接 默认 8  
  27.         max-idle: 8  
  28.         # 连接池中的最小空闲连接 默认 0  
  29.         min-idle: 0  

 这里的配置不多解释,需要解释的已经标注注释。

4.3 RedisTemplate 使用方式

4.3.1 创建实体类 User.java

代码清单:spring-boot-redis/src/main/java/com/springboot/springbootredis/model/User.java

Java代码 
  1. @Data  
  2. @AllArgsConstructor  
  3. @NoArgsConstructor  
  4. public class User implements Serializable {  
  5.   
  6.     private static final long serialVersionUID = 662692455422902539L;  
  7.     private Long id;  
  8.     private String name;  
  9.     private int age;  
  10. }  

 

4.3.2 自定义 RedisTemplate

默认情况下的模板只能支持 RedisTemplate<String, String> ,也就是只能存入字符串,这在开发中是不友好的,所以自定义模板是很有必要的,当自定义了模板又想使用 String 存储这时候就可以使用 StringRedisTemplate 的方式,它们并不冲突,添加配置类 RedisCacheConfig.java ,代码如下:

代码清单:spring-boot-redis/src/main/java/com/springboot/springbootredis/config/RedisCacheConfig.java

Java代码 
  1. @Configuration  
  2. @AutoConfigureAfter(RedisAutoConfiguration.class)  
  3. public class RedisCacheConfig {  
  4.   
  5.     @Bean  
  6.     public RedisTemplate<String, Serializable> redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory) {  
  7.         RedisTemplate<String, Serializable> template = new RedisTemplate<>();  
  8.         template.setKeySerializer(new StringRedisSerializer());  
  9.         template.setValueSerializer(new GenericJackson2JsonRedisSerializer());  
  10.         template.setConnectionFactory(redisConnectionFactory);  
  11.         return template;  
  12.     }  
  13. }  

 

4.3.3 测试接口 UserController.java

代码清单:

Java代码 
  1. @RestController  
  2. @Slf4j  
  3. public class UserController {  
  4.   
  5.     @Autowired  
  6.     private StringRedisTemplate stringRedisTemplate;  
  7.   
  8.     @Autowired  
  9.     RedisTemplate<String, Serializable> redisCacheTemplate;  
  10.   
  11.     @Autowired  
  12.     UserService userService;  
  13.   
  14.     @GetMapping("/test")  
  15.     public void test() {  
  16.         stringRedisTemplate.opsForValue().set("geekdigging""https://www.geekdigging.com/");  
  17.   
  18.         log.info("当前获取对象:{}",stringRedisTemplate.opsForValue().get("geekdigging"));  
  19.   
  20.         redisCacheTemplate.opsForValue().set("geekdigging.com"new User(1L, "geekdigging"18));  
  21.   
  22.         User user = (User) redisCacheTemplate.opsForValue().get("geekdigging.com");  
  23.   
  24.         log.info("当前获取对象:{}", user);  
  25.     }  
  26. }  

 

4.3.4 测试

启动服务,打开浏览器访问链接:http://localhost:8080/test ,查看控制台日志打印,如下:

Java代码 
  1. 2019-09-24 23:49:30.191  INFO 19108 --- [nio-8080-exec-1] c.s.s.controller.UserController          : 当前获取对象:https://www.geekdigging.com/  
  2. 2019-09-24 23:49:30.243  INFO 19108 --- [nio-8080-exec-1] c.s.s.controller.UserController         

 测试成功。

4.4 使用 Spring Cache 集成 Redis

4.4.1 Spring Cache 特点

Spring 3.1 引入了激动人心的基于注释(annotation)的缓存(cache)技术,它本质上不是一个具体的缓存实现方案(例如 EHCache 或者 Redis),而是一个对缓存使用的抽象,通过在既有代码中添加少量它定义的各种 annotation,即能够达到缓存方法的返回对象的效果。

Spring Cache 具备相当的好的灵活性,不仅能够使用 SpEL(Spring Expression Language)来定义缓存的 key 和各种 condition,还提供开箱即用的缓存临时存储方案,也支持和主流的专业缓存例如 EHCache、Redis、Guava 的集成。

  • 基于 annotation 即可使得现有代码支持缓存
  • 开箱即用 Out-Of-The-Box,不用安装和部署额外第三方组件即可使用缓存
  • 支持 Spring Express Language,能使用对象的任何属性或者方法来定义缓存的 key 和 condition
  • 支持 AspectJ,并通过其实现任何方法的缓存支持
  • 支持自定义 key 和自定义缓存管理者,具有相当的灵活性和扩展性

4.4.2 定义接口 UserService.java

代码清单:spring-boot-redis/src/main/java/com/springboot/springbootredis/service/UserService.java

Java代码 
  1. public interface UserService {  
  2.     User save(User user);  
  3.   
  4.     User get(Long id);  
  5.   
  6.     void delete(Long id);  
  7. }  

 

4.4.3 接口实现 UserServiceImpl.java

代码清单:spring-boot-redis/src/main/java/com/springboot/springbootredis/service/impl/UserServiceImpl.java

Java代码 
  1. @Service  
  2. @Slf4j  
  3. public class UserServiceImpl implements UserService {  
  4.   
  5.     private static final Map<Long, User> USER_MAP = new HashMap<>();  
  6.   
  7.     static {  
  8.         USER_MAP.put(1L, new User(1L, "geekdigging.com"18));  
  9.         USER_MAP.put(2L, new User(2L, "geekdigging.com"19));  
  10.         USER_MAP.put(3L, new User(3L, "geekdigging.com"20));  
  11.     }  
  12.   
  13.     @CachePut(value = "user", key = "#user.id")  
  14.     @Override  
  15.     public User save(User user) {  
  16.         USER_MAP.put(user.getId(), user);  
  17.         log.info("进入 save 方法,当前存储对象:{}",  user);  
  18.         return user;  
  19.     }  
  20.   
  21.     @Cacheable(value = "user", key = "#id")  
  22.     @Override  
  23.     public User get(Long id) {  
  24.         log.info("进入 get 方法,当前获取对象:{}",  USER_MAP.get(id));  
  25.         return USER_MAP.get(id);  
  26.     }  
  27.   
  28.     @CacheEvict(value = "user", key = "#id")  
  29.     @Override  
  30.     public void delete(Long id) {  
  31.         USER_MAP.remove(id);  
  32.         log.info("进入 delete 方法,删除成功");  
  33.     }  
  34. }  

 为了方便演示数据库操作,直接定义了一个 Map<Long, User> USER_MAP ,这里的核心就是三个注解 @Cacheable 、 @CachePut 、 @CacheEvict 。

4.4.3.1 @Cacheable

根据方法的请求参数对其结果进行缓存

  • key: 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合(如:@Cacheable(value="user",key="#userName")
  • value: 缓存的名称,必须指定至少一个(如:@Cacheable(value="user") 或者 @Cacheable(value={"user1","use2"}) )
  • condition: 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存(如:@Cacheable(value = "user", key = "#id",condition = "#id < 10")
4.4.3.2 @CachePut

根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用

  • key: 同上
  • value: 同上
  • condition: 同上
4.4.3.3 @CachEvict

根据条件对缓存进行清空

  • key: 同上
  • value: 同上
  • condition: 同上
  • allEntries: 是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存(如: @CacheEvict(value = "user", key = "#id", allEntries = true) )
  • beforeInvocation: 是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存(如: @CacheEvict(value = "user", key = "#id", beforeInvocation = true) )

4.4.4 启动主类

代码清单:spring-boot-redis/src/main/java/com/springboot/springbootredis/SpringBootRedisApplication.java

Java代码 
  1. @SpringBootApplication  
  2. @EnableCaching  
  3. public class SpringBootRedisApplication {  
  4.   
  5.     public static void main(String[] args) {  
  6.         SpringApplication.run(SpringBootRedisApplication.class, args);  
  7.     }  
  8.   
  9. }  

 

  • 这里需增加注解 @EnableCaching 开启 Spring Session。

4.4.5 增加测试接口

代码清单:spring-boot-redis/src/main/java/com/springboot/springbootredis/controller/UserController.java

Java代码 
  1. @GetMapping("/test1")  
  2. public void test1() {  
  3.     User user = userService.save(new User(4L, "geekdigging.com"35));  
  4.   
  5.     log.info("当前 save 对象:{}", user);  
  6.   
  7.     user = userService.get(1L);  
  8.   
  9.     log.info("当前 get 对象:{}", user);  
  10.   
  11.     userService.delete(5L);  
  12. }  

 

4.4.6 测试

启动服务,打开浏览器访问链接:http://localhost:8080/test ,刷新页面,控制台日志打印如下:

Java代码 
  1. 2019-09-25 00:07:21.887  INFO 21484 --- [nio-8080-exec-1] c.s.s.service.impl.UserServiceImpl       : 进入 save 方法,当前存储对象:User(id=4, name=geekdigging.com, age=35)  
  2. 2019-09-25 00:07:21.897  INFO 21484 --- [nio-8080-exec-1] c.s.s.controller.UserController          : 当前 save 对象:User(id=4, name=geekdigging.com, age=35)  
  3. 2019-09-25 00:07:21.899  INFO 21484 --- [nio-8080-exec-1] c.s.s.service.impl.UserServiceImpl       : 进入 get 方法,当前获取对象:User(id=1, name=geekdigging.com, age=18)  
  4. 2019-09-25 00:07:21.900  INFO 21484 --- [nio-8080-exec-1] c.s.s.controller.UserController          : 当前 get 对象:User(id=1, name=geekdigging.com, age=18)  
  5. 2019-09-25 00:07:21.901  INFO 21484 --- [nio-8080-exec-1] c.s.s.service.impl.UserServiceImpl       : 进入 delete 方法,删除成功  

 再次刷新页面,查看控制台日志:

Java代码 
  1. 2019-09-25 00:08:54.076  INFO 21484 --- [nio-8080-exec-7] c.s.s.service.impl.UserServiceImpl       : 进入 save 方法,当前存储对象:User(id=4, name=geekdigging.com, age=35)  
  2. 2019-09-25 00:08:54.077  INFO 21484 --- [nio-8080-exec-7] c.s.s.controller.UserController          : 当前 save 对象:User(id=4, name=geekdigging.com, age=35)  
  3. 2019-09-25 00:08:54.079  INFO 21484 --- [nio-8080-exec-7] c.s.s.controller.UserController          : 当前 get 对象:User(id=1, name=geekdigging.com, age=18)  
  4. 2019-09-25 00:08:54.079  INFO 21484 --- [nio-8080-exec-7] c.s.s.service.impl.UserServiceImpl       : 进入 delete 方法,删除成功  

 结果和我们期望的一致,可以看到增删改查中,查询是没有日志输出的,因为它直接从缓存中获取的数据,而添加、修改、删除都是会进入 UserServiceImpl 的方法内执行具体的业务代码。

4.5 Session 共享

4.5.1 Spring Session 简介

Spring Session 提供了一套创建和管理 Servlet HttpSession 的方案。Spring Session 提供了集群 Session(Clustered Sessions)功能,默认采用外置的 Redis 来存储 Session 数据,以此来解决 Session 共享的问题。

4.5.2 启动主类 SpringBootRedisApplication.java

代码清单:spring-boot-redis/src/main/java/com/springboot/springbootredis/SpringBootRedisApplication.java

Java代码 
  1. @SpringBootApplication  
  2. @EnableCaching  
  3. @EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)  
  4. public class SpringBootRedisApplication {  
  5.   
  6.     public static void main(String[] args) {  
  7.         SpringApplication.run(SpringBootRedisApplication.class, args);  
  8.     }  
  9.   
  10. }  

 

  • maxInactiveIntervalInSeconds: 设置 Session 失效时间,使用 Spring Session 之后,原 Spring Boot 配置文件 application.yml 中的 server.session.timeout 属性不再生效。

4.5.3 增加测试接口

代码清单:spring-boot-redis/src/main/java/com/springboot/springbootredis/controller/UserController.java

Java代码 
  1. @GetMapping("/getBlogUrl")  
  2. public String getSessionId(HttpServletRequest request) {  
  3.     String url = (String) request.getSession().getAttribute("url");  
  4.     if (StringUtils.isEmpty(url)) {  
  5.         request.getSession().setAttribute("url""https://www.geekdigging.com/");  
  6.     }  
  7.     log.info("获取session内容为: {}", request.getSession().getAttribute("url"));  
  8.     return request.getRequestedSessionId();  
  9. }  

 

4.5.4 测试

启动服务,打开浏览器访问链接:http://localhost:8080/getBlogUrl ,查看 Redis 当前存储内容,如下图:

 

Spring Boot (五): Redis缓存使用姿势盘点
 

 

其中 1569339180000 为失效时间,意思是这个时间后 Session 失效, b2522824-1094-478e-a435-554a551bc8bb 为 SessionId 。

4.5.6 如何在多台服务中共享 Session

按照上面的步骤在另一个项目中再次配置一次,启动后自动就进行了 Session 共享。

分享到:
评论

相关推荐

    3.1、spring boot redis注解缓存Cacheable (value) 1

    在spring boot 项目中,使用redis缓存机制需要引入相关依赖关系。首先,在pom.xml文件中引入spring boot 父节点依赖关系: ```xml &lt;groupId&gt;org.springframework.boot &lt;artifactId&gt;spring-boot-starter-parent ...

    Spring Boot整合Redis做集中式缓存

    在一些要求高一致性(任何数据变化都能及时的被查询到)的系统和应用中,就不能再使用EhCache来解决了,这个时候使用集中式缓存是个不错的选择,因此本文将介绍如何在Spring Boot的缓存支持中使用Redis进行数据缓存...

    35.[视频] Spring Boot集成Redis实现缓存机制【从零开始学Spring Boot】

    - **启用Redis缓存**:通过在配置类中启用`@EnableCaching`注解,Spring Boot将自动扫描并处理缓存注解。 2. **Redis缓存注解** - **@Cacheable**:此注解用在方法上,表示该方法的结果会被缓存。可以通过指定`...

    Spring Boot:SpringBoot集成缓存技术Redis.docx

    Spring Boot:SpringBoot集成缓存技术Redis.docx

    Spring Boot整合redis

    以上就是Spring Boot整合Redis的相关知识点,包括配置、数据操作、模板引擎Thymeleaf、数据源Druid、声明式事务管理和Redis事务的使用。通过这些知识,你可以构建一个具备数据缓存能力的Web应用。

    Spring Boot整合Redis的完整步骤

    本文将详细介绍Spring Boot整合Redis的完整步骤,包括Spring Boot对Redis的支持、添加依赖、配置RedisTemplate和StringRedisTemplate、使用Redis缓存等。 一、Spring Boot对Redis的支持 Spring Boot对Redis的支持...

    spring boot+redis单机与集群.zip

    总结来说,这个压缩包文件的内容将涵盖Spring Boot项目中集成Redis的基本步骤,包括设置单机和集群模式,以及如何在应用中使用Redis进行数据缓存。对于初学者,这将是一个很好的实践指南,而对于有经验的开发者,也...

    spring-boot-redis-annotation-demo:spring boot —— redis 缓存注解使用示例项目

    spring boot —— redis 缓存注解使用教程 示例项目地址: 依赖 在pom文件添加如下依赖 &lt;groupId&gt;org.springframework.boot &lt;artifactId&gt;spring-boot-starter-data-redis 配置 在application.yml配置文件添加...

    springboot-mybatis-redis缓存集成

    8. 清除缓存:使用`@CacheEvict`注解清除指定的缓存项。 9. 测试:编写测试用例,验证缓存功能是否正常工作。 通过以上步骤,你可以成功地将Spring Boot、MyBatis和Redis集成,实现数据缓存,提高系统的响应速度和...

    详解Spring Boot使用redis实现数据缓存

    在本文中,我们将深入探讨如何在Spring Boot应用中利用Redis作为数据缓存系统。Spring Boot以其简化微服务开发的特性,结合Redis的高效缓存能力,可以为应用程序提供高效的性能优化。 首先,集成Spring Boot与Redis...

    使用maven简单搭建Spring mvc + redis缓存

    本文将详细讲解如何使用Maven来简单搭建一个集成了Spring MVC和Redis缓存的项目。 首先,让我们从Maven开始。Maven是一个项目管理工具,它帮助开发者管理依赖、构建项目以及执行自动化测试。在创建新项目时,我们...

    Spring boot 集成 redis (解决String类型乱码) 缓存用redis

    最后,启动Spring Boot应用,现在你的系统已经集成了Redis缓存,并解决了String类型的乱码问题。在实际应用中,还可以根据需求调整缓存策略,比如设置过期时间、缓存更新策略等。 总的来说,Spring Boot与Redis的集...

    spring boot 集成redis代码

    在本文中,我们将深入探讨如何在Spring Boot应用中集成Redis,以便利用其高效的数据存储和检索功能。Redis是一个开源的、内存数据结构存储系统,它可以用作数据库、缓存和消息代理。Spring Boot是Spring框架的一个轻...

    Spring boot整合分布式缓存RedisSpring-redis-redission.zip

    通过上述步骤,你可以成功地在Spring Boot项目中集成Redis和Redission,实现高效、可靠的分布式缓存方案。记得在实际开发中根据业务需求选择合适的数据结构和功能,以达到最佳性能和可维护性。同时,定期检查和优化...

    Spring Boot整合Redis实现发布/订阅功能教程配套源码

    Redis作为一个高性能的内存数据存储,除了支持缓存和持久化数据,它还有很多功能,如:在博主分享的上一篇文章中,我们介绍了使用Redis实现的延迟队列功能 【Spring Boot整合Redis通过Zset数据类型+定时任务实现延迟...

    spring boot - redis-1

    8. **Redis缓存管理** Spring Boot可以轻松实现基于注解的缓存管理,例如使用`@Cacheable`、`@CacheEvict`、`@CachePut`等注解,实现方法级别的缓存控制。 9. **RedisTemplate高级用法** RedisTemplate还支持事务...

    Spring boot 和 Redis集成例子.zip

    在现代的Web应用开发中,Spring Boot和Redis的结合使用非常常见,因为它们能提供高效、灵活的数据存储和快速响应。Spring Boot简化了基于Spring的应用程序的开发过程,而Redis则是一个高性能的键值数据库,适合处理...

    基于SpringBoot2+Jpa+SpringSecurity+redis+Vue的前后端分离系统

    系统缓存管理 将redis的操作可视化,提供对redis的基本操作 Sql监控 采用 druid 监控数据库访问性能 技术栈 基础框架:Spring Boot 2.1.0.RELEASE 持久层框架:Spring boot Jpa 安全框架:Spring Security 缓存框架...

    Spring boot基于redis实现附近的人

    2. **Redis Hash存储**:使用Redis的HSET命令将用户信息以Hash的形式存储,键为用户ID,字段包括用户属性。 3. **计算距离**:使用地理坐标公式(如Haversine公式)计算用户之间的距离。这涉及到对经纬度的处理,...

    Spring boot -redis

    在 Spring Boot 中整合 Redis,我们可以利用 Spring Data Redis 模块,它提供了与 Redis 交互的高级抽象,简化了开发过程。Spring Data Redis 提供了 RedisTemplate 和 StringRedisTemplate 两个核心模板类,用于...

Global site tag (gtag.js) - Google Analytics