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

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 玩转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,都是允许你手动切换的(只是完全没有必要而已)。


相关文章
|
12天前
|
缓存 负载均衡 监控
135_负载均衡:Redis缓存 - 提高缓存命中率的配置与最佳实践
在现代大型语言模型(LLM)部署架构中,缓存系统扮演着至关重要的角色。随着LLM应用规模的不断扩大和用户需求的持续增长,如何构建高效、可靠的缓存架构成为系统性能优化的核心挑战。Redis作为业界领先的内存数据库,因其高性能、丰富的数据结构和灵活的配置选项,已成为LLM部署中首选的缓存解决方案。
|
13天前
|
缓存 运维 监控
Redis 7.0 高性能缓存架构设计与优化
🌟蒋星熠Jaxonic,技术宇宙中的星际旅人。深耕Redis 7.0高性能缓存架构,探索函数化编程、多层缓存、集群优化与分片消息系统,用代码在二进制星河中谱写极客诗篇。
|
27天前
|
存储 缓存 NoSQL
Redis专题-实战篇二-商户查询缓存
本文介绍了缓存的基本概念、应用场景及实现方式,涵盖Redis缓存设计、缓存更新策略、缓存穿透问题及其解决方案。重点讲解了缓存空对象与布隆过滤器的使用,并通过代码示例演示了商铺查询的缓存优化实践。
119 1
Redis专题-实战篇二-商户查询缓存
|
28天前
|
缓存 NoSQL 关系型数据库
Redis缓存和分布式锁
Redis 是一种高性能的键值存储系统,广泛用于缓存、消息队列和内存数据库。其典型应用包括缓解关系型数据库压力,通过缓存热点数据提高查询效率,支持高并发访问。此外,Redis 还可用于实现分布式锁,解决分布式系统中的资源竞争问题。文章还探讨了缓存的更新策略、缓存穿透与雪崩的解决方案,以及 Redlock 算法等关键技术。
存储 JSON Java
271 0
|
1月前
|
NoSQL Java 调度
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
分布式锁是分布式系统中用于同步多节点访问共享资源的机制,防止并发操作带来的冲突。本文介绍了基于Spring Boot和Redis实现分布式锁的技术方案,涵盖锁的获取与释放、Redis配置、服务调度及多实例运行等内容,通过Docker Compose搭建环境,验证了锁的有效性与互斥特性。
107 0
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
|
5月前
|
缓存 NoSQL 关系型数据库
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
|
5月前
|
缓存 NoSQL Java
Redis+Caffeine构建高性能二级缓存
大家好,我是摘星。今天为大家带来的是Redis+Caffeine构建高性能二级缓存,废话不多说直接开始~
777 0
|
5月前
|
消息中间件 缓存 NoSQL
基于Spring Data Redis与RabbitMQ实现字符串缓存和计数功能(数据同步)
总的来说,借助Spring Data Redis和RabbitMQ,我们可以轻松实现字符串缓存和计数的功能。而关键的部分不过是一些"厨房的套路",一旦你掌握了这些套路,那么你就像厨师一样可以准备出一道道饕餮美食了。通过这种方式促进数据处理效率无疑将大大提高我们的生产力。
205 32
|
5月前
|
缓存 NoSQL Java
Redis:现代服务端开发的缓存基石与电商实践-优雅草卓伊凡
Redis:现代服务端开发的缓存基石与电商实践-优雅草卓伊凡
117 5
Redis:现代服务端开发的缓存基石与电商实践-优雅草卓伊凡

热门文章

最新文章