玩转Spring Cache --- 整合分布式缓存Redis Cache(使用Lettuce、使用Spring Data Redis)【享学Spring】(上)

简介: 玩转Spring Cache --- 整合分布式缓存Redis Cache(使用Lettuce、使用Spring Data Redis)【享学Spring】(上)

前言


最近都在聊Spring的缓存抽象Spring Cache,上篇文章深入介绍了Spring Cache集成进程缓存的第三方组件如Caffeine、Ehcache,若对此篇文章感兴趣,可移步观看:【小家Spring】玩转Spring Cache — 整合进程缓存之王Caffeine Cache和Ehcache3.x


我们知道现在的应用大都以微服务的方式进行分布式部署,因此如果仅仅使用本地缓存是 满足不了/难以满足 我们需求的(Infinispan这种基于本地内存实现的分布式缓存不在本文讨论范围~)。针对分布式场景下的缓存应用,我们急需要一个高可用的、快速的、中心化的、分布式的缓存产品。然后在众多此场景的实现产品中,Redis以它众多优秀的特性脱颖而出。


so,本文就以大伙最关心、最熟悉的Redis这个缓存产品为例,让它和Spring Cache集成,达到分布式中心缓存的效果(支持缓存直接直接操作)。


Redis:一个基于键值对存储的NoSQL内存数据库,可存储复杂的数据结构,如List, Set, Hashes。

关于Redis的单线程、数据结构、序列化、网络IO、高吞吐等高级特性,不是本文讨论的范围。本文只讨论集成注解缓存的k-v结构


Spring Data Redis简介和使用示例


Spring构建了自己庞大的生态,它对很多优秀的、流行的产品提供了一整套的整合、解决方案。Redis在缓存界这么广受欢迎,Spring Data工程中自然少不了它,它就是Spring Data Redis。


Spring Data Redis对Redis底层开发包(Jedis、Lettuce、JRedis、RJC)进行了高度封装。RedisTemplate封装提供了redis各种操作、异常处理及序列化,完全屏蔽里底层实现(使用者面向Spring Data编程即可,可完全不用关心底层到底使用的是Jedis or Lettuce)。


Spring Data Redis这个Jar的依赖包如下:


image.png


另外有个使用的Tips需要注意:在Spring Data Redis的使用方面上,我们还需要重视版本的差异:


其实我一直在强调版本意识,不管是在Spring上、JDK上,还是MyBatis,版本意识对你做架构都非常的重要


Spring Data Redis1.x截图:


image.png


Spring Data Redis2.x截图:


image.png


版本的差异从包结构上就能一目了然。具体到源码处,从RedisConnectionFactory接口的继承图也能看出差异:


image.png


image.png

由图可知,从2.x版本开始,Spring就只为我们保留了jedis和lettuce。

lettuce是redis连接池未来的发展趋势,2.x开始已经推荐使用lettuce作为访问redis的client客户端。


不管用什么客户端,对使用者应该都是透明的,因为在开发过程中,没有极其特殊的情况,应该规定只允许使用RedisTemplate来操作Redis。


使用Jedis作为Client操作Redis示例


虽然说Jedis有多线程安全问题,并且它的性能也堪忧,大有被淘汰的趋势。但是,但是,但是毕竟它还仍旧还是当下的主流的Java访问Redis的客户端,所以本文也有必要把它的使用说一下,供以参考:


第一步:导包(本文以2.x为例)

<!-- 使用Spring Data Redis 操作Redis缓存 -->
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>2.1.9.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.10.2</version>
</dependency>


第二步:准备Config配置文件

//@EnableCaching // 因为此处我没准备CacheManager,暂时关闭缓存注解
@Configuration
public class CacheConfig extends CachingConfigurerSupport {
    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
        // 2.0后的写法
        configuration.setHostName("10.102.132.150");
        //configuration.setPassword(RedisPassword.of("123456"));
        configuration.setPort(6379);
        configuration.setDatabase(0);
        JedisConnectionFactory factory = new JedisConnectionFactory(configuration);
        // Spring Data Redis1.x这么来设置  2.0后建议使用RedisStandaloneConfiguration来取代
        //factory.setHostName("10.102.132.150");
        //factory.setPassword("123456");
        //factory.setPort(6379);
        //factory.setDatabase(0);
        return factory;
    }
    @Bean
    public RedisTemplate<String, String> stringRedisTemplate() {
        RedisTemplate<String, String> redisTemplate = new StringRedisTemplate();
        redisTemplate.setConnectionFactory(redisConnectionFactory());
        return redisTemplate;
    }
}


运行单元测试:


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {RootConfig.class, CacheConfig.class})
public class TestSpringBean {
    @Autowired
    private RedisConnectionFactory redisConnectionFactory;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Test
    public void test1() {
        System.out.println(redisConnectionFactory);
        System.out.println(redisConnectionFactory.getConnection());
        //System.out.println(redisConnectionFactory.getClusterConnection()); //InvalidDataAccessApiUsageException: Cluster is not configured!
        //System.out.println(redisConnectionFactory.getSentinelConnection()); // InvalidDataAccessResourceUsageException: No Sentinels configured
        System.out.println(redisTemplate);
        redisTemplate.opsForValue().set("name", "fsx");
        System.out.println(redisTemplate.opsForValue().get("name"));
    }
}


打印输出:


org.springframework.data.redis.connection.jedis.JedisConnectionFactory@238b521e
org.springframework.data.redis.connection.jedis.JedisConnection@1cefc4b3
org.springframework.data.redis.core.StringRedisTemplate@2b27cc70
fsx


并且Redis Server端也能查看到key为“name”的值:


image.png


由此证明我们的缓存配置都能正常work了,能够使用RedisTempate操作Redis了。部分很简单有木有,只需要简单的两步即可达到目的~


关于Jedis或者说RedisTemplate的详细使用,显然也不是本文的重点,有兴趣的可自行研究,或者出门左拐~


使用Lettuce作为Client操作Redis示例

Lettuce作为新时代的Redis客户端,它势必成为将来的主流(其实现在也很主流了,比如SpringBoot2.0后默认就使用它作为Redis的Client访问)。


第一步:同样的导包(此处导入lettuce作为客户端)

<!-- 使用Spring Data Redis 操作Redis缓存 -->
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>2.1.9.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.lettuce/lettuce-core -->
<dependency>
    <groupId>io.lettuce</groupId>
    <artifactId>lettuce-core</artifactId>
    <version>5.1.7.RELEASE</version>
</dependency>


第二步:准备Config配置文件


//@EnableCaching
@Configuration
public class CacheConfig extends CachingConfigurerSupport {
    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        // RedisStandaloneConfiguration这个配置类是Spring Data Redis2.0后才有的~~~
        RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
        // 2.0后的写法
        configuration.setHostName("10.102.132.150");
        //configuration.setPassword(RedisPassword.of("123456"));
        configuration.setPort(6379);
        configuration.setDatabase(0);
        LettuceConnectionFactory factory = new LettuceConnectionFactory(configuration);
        // Spring Data Redis1.x这么来设置  2.0后建议使用RedisStandaloneConfiguration来取代
        //factory.setHostName("10.102.132.150");
        //factory.setPassword("123456");
        //factory.setPort(6379);
        //factory.setDatabase(0);
        return factory;
    }
    @Bean
    public RedisTemplate<String, String> stringRedisTemplate() {
        RedisTemplate<String, String> redisTemplate = new StringRedisTemplate();
        redisTemplate.setConnectionFactory(redisConnectionFactory());
        return redisTemplate;
    }
}


用上了Spring Data Redis2.0提供的RedisStandaloneConfiguration配置类后,配置步骤和Jedis的一毛一样


运行如上的单元测试,打印结果如下:


org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory@59942b48
14:35:00.798 [main] INFO  io.lettuce.core.EpollProvider - Starting without optional epoll library
14:35:00.800 [main] INFO  io.lettuce.core.KqueueProvider - Starting without optional kqueue library
org.springframework.data.redis.connection.lettuce.LettuceConnection@3cf7298d
org.springframework.data.redis.core.StringRedisTemplate@1ff55ff
fsx


从日志中会发现多输出了两句info日志,结果都是ok的,能正常work。




说明:SpringBoot1.x最终依赖的是Spring Data Redis 1.8.xx,默认导入使用的是Jedis客户端,版本号为2.9.x(非最新的3.x,不兼容,慎用)

SpringBoot2.0开始,依赖的是Spring Data Redis 2.x/x,并且默认导入使用的是Lettuce客户端,版本号是从5.x.x开始

当然,不管是Boot1.x或者2.x,都是允许你手动切换的(只是完全没有必要而已)。


相关文章
|
人工智能 Java Nacos
基于 Spring AI Alibaba + Nacos 的分布式 Multi-Agent 构建指南
本文将针对 Spring AI Alibaba + Nacos 的分布式多智能体构建方案展开介绍,同时结合 Demo 说明快速开发方法与实际效果。
6127 122
|
监控 Java API
Spring Boot 3.2 结合 Spring Cloud 微服务架构实操指南 现代分布式应用系统构建实战教程
Spring Boot 3.2 + Spring Cloud 2023.0 微服务架构实践摘要 本文基于Spring Boot 3.2.5和Spring Cloud 2023.0.1最新稳定版本,演示现代微服务架构的构建过程。主要内容包括: 技术栈选择:采用Spring Cloud Netflix Eureka 4.1.0作为服务注册中心,Resilience4j 2.1.0替代Hystrix实现熔断机制,配合OpenFeign和Gateway等组件。 核心实操步骤: 搭建Eureka注册中心服务 构建商品
1723 3
|
存储 安全 Java
管理 Spring 微服务中的分布式会话
在微服务架构中,管理分布式会话是确保用户体验一致性和系统可扩展性的关键挑战。本文探讨了在 Spring 框架下实现分布式会话管理的多种方法,包括集中式会话存储和客户端会话存储(如 Cookie),并分析了它们的优缺点。同时,文章还涵盖了与分布式会话相关的安全考虑,如数据加密、令牌验证、安全 Cookie 政策以及服务间身份验证。此外,文中强调了分布式会话在提升系统可扩展性、增强可用性、实现数据一致性及优化资源利用方面的显著优势。通过合理选择会话管理策略,结合 Spring 提供的强大工具,开发人员可以在保证系统鲁棒性的同时,提供无缝的用户体验。
362 0
|
NoSQL 安全 Java
深入理解 RedisConnectionFactory:Spring Data Redis 的核心组件
在 Spring Data Redis 中,`RedisConnectionFactory` 是核心组件,负责创建和管理与 Redis 的连接。它支持单机、集群及哨兵等多种模式,为上层组件(如 `RedisTemplate`)提供连接抽象。Spring 提供了 Lettuce 和 Jedis 两种主要实现,其中 Lettuce 因其线程安全和高性能特性被广泛推荐。通过手动配置或 Spring Boot 自动化配置,开发者可轻松集成 Redis,提升应用性能与扩展性。本文深入解析其作用、实现方式及常见问题解决方法,助你高效使用 Redis。
1667 4
|
NoSQL Java 调度
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
分布式锁是分布式系统中用于同步多节点访问共享资源的机制,防止并发操作带来的冲突。本文介绍了基于Spring Boot和Redis实现分布式锁的技术方案,涵盖锁的获取与释放、Redis配置、服务调度及多实例运行等内容,通过Docker Compose搭建环境,验证了锁的有效性与互斥特性。
1099 0
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
|
负载均衡 Java API
《深入理解Spring》Spring Cloud 构建分布式系统的微服务全家桶
Spring Cloud为微服务架构提供一站式解决方案,涵盖服务注册、配置管理、负载均衡、熔断限流等核心功能,助力开发者构建高可用、易扩展的分布式系统,并持续向云原生演进。
|
缓存 Java 应用服务中间件
Spring Boot配置优化:Tomcat+数据库+缓存+日志,全场景教程
本文详解Spring Boot十大核心配置优化技巧,涵盖Tomcat连接池、数据库连接池、Jackson时区、日志管理、缓存策略、异步线程池等关键配置,结合代码示例与通俗解释,助你轻松掌握高并发场景下的性能调优方法,适用于实际项目落地。
2124 5
|
存储 缓存 Java
Spring中@Cacheable、@CacheEvict以及其他缓存相关注解的实用介绍
缓存是提升应用性能的重要技术,Spring框架提供了丰富的缓存注解,如`@Cacheable`、`@CacheEvict`等,帮助开发者简化缓存管理。本文介绍了如何在Spring中配置缓存管理器,使用缓存注解优化数据访问,并探讨了缓存的最佳实践,以提升系统响应速度与可扩展性。
523 0
Spring中@Cacheable、@CacheEvict以及其他缓存相关注解的实用介绍
|
消息中间件 缓存 NoSQL
基于Spring Data Redis与RabbitMQ实现字符串缓存和计数功能(数据同步)
总的来说,借助Spring Data Redis和RabbitMQ,我们可以轻松实现字符串缓存和计数的功能。而关键的部分不过是一些"厨房的套路",一旦你掌握了这些套路,那么你就像厨师一样可以准备出一道道饕餮美食了。通过这种方式促进数据处理效率无疑将大大提高我们的生产力。
502 32
|
NoSQL Java Redis
Redis基本数据类型及Spring Data Redis应用
Redis 是开源高性能键值对数据库,支持 String、Hash、List、Set、Sorted Set 等数据结构,适用于缓存、消息队列、排行榜等场景。具备高性能、原子操作及丰富功能,是分布式系统核心组件。
1027 2

热门文章

最新文章