SpringBoot集成Redis使用心得
记录一下最近在从零搭建项目时集成Redis的使用心得,主要内容如下:
- SpringBoot如何引入Redis;
- SpringBoot引入Redis依赖后,为什么不能直接注入RedisTemplate;
- SpringBoot中Redis的序列化方式;
- 自动装配默认使用的Redis客户端为什么是Lettuce;
SpringBoot如何引入Redis
首先,如果作为初次在SpringBoot项目中使用Redis的人,可以按照如下方法查找关于Redis的依赖包。
-
浏览器打开spring官网,找到SpringBoot项目。
-
点击当前版本(CURRENT)SpringBoot的参考资料(Reference Doc.)。
-
进入文档后,在搜索栏(Search)搜索Redis,一般第一个就是对应的文档目录。
-
根据文档内容,可以了解到SpringBoot提供了一个
spring-boot-starter-data-redis
依赖包用于管理SpringBoot中关于Redis的依赖配置。并且在文档中还有大致的使用说明和示例。
因此,要想使用Redis,只需要在SpringBoot项目中引入如下依赖即可:
1 | <dependency> |
spring-boot-starter-data-redis
依赖的版本号在 spring-boot-dependencies
有依赖管理。
如果想要开启Redis连接池,则需要依赖 commons-pool2
:
1 | <dependency> |
同样的,commons-pool2
依赖的版本号在 spring-boot-dependencies
有依赖管理。
SpringBoot项目为什么不能直接注入RedisTemplate
这个问题有一点歧义,其实SpringBoot项目在引入spring-boot-starter-data-redis
依赖后,是可以直接注入的,通过 RedisAutoConfiguration
源码分析可知,它默认注册了两个RedisTemplate类型的Bean。
1 |
|
Spring依赖注入的原理是基于Bean类型+名称确定,通过@Autowried
注入唯一RedisTemplate对象时,可以注入下面两种:
- RedisTemplate<Object, Object> redisTemplate;
- StringRedisTemplate stringRedisTemplate;
StringRedisTemplate
继承于RedisTemplate<String, String>
,因此从Spring容器获取所有RedisTemplate的Bean对象时,StringRedisTemplate
也会在其中。
细心点可以发现,StringRedisTemplate
和RedisTemplate<Object, Object>
主要是范型类型不一样,所以这里就涉及到一个知识点。
在Java中,尽管泛型类型在运行时会被擦除,但在 Spring 的上下文中,Bean 的定义还是会包含泛型信息,这样可以在自动装配时进行更加精确的匹配。
因此,通过
@Autowired
自动注入Bean时,Spring会尝试匹配 Bean 的类型和泛型参数。
所以,回到问题本身,如果在项目代码中,使用如下方式注入,就会报错:
1 | // 报错,因为SpringBoot自动装配注册的Bean为RedisTemplate<Object, Object>类型 |
如果想要具备RedisTemplate<String, Object>
类型的Bean,就得手动注册一个。
SpringBoot中Redis的序列化方式
准确来说,应该是RedisTemplate
的序列化方式,在 Spring Data Redis 中,RedisTemplate 使用序列化器(Serializer)将 Java 对象序列化为二进制数据(字节数组),并反序列化为 Java 对象。
默认情况下,RedisTemplate
会使用 JdkSerializationRedisSerializer
来序列化 key
和 value
,这意味着对象会使用 Java 自带的序列化机制(Serializable
接口)进行序列化。
序列化器的接口为 RedisSerializer
,Spring Data Redis中默认实现了几种序列化方式,常见的有:
-
StringRedisSerializer:将字符串序列化为字节数组,常用于序列化
key
,因为 Redis 的key
通常是字符串类型。 -
JdkSerializationRedisSerializer:使用 Java 序列化机制,将对象序列化为字节数组,这也是默认的
RedisTemplate
序列化方式。 -
Jackson2JsonRedisSerializer:使用 Jackson 库将对象序列化为 JSON 字符串,适合存储和读取 JSON 数据。
-
GenericJackson2JsonRedisSerializer:类似于
Jackson2JsonRedisSerializer
,但更通用,可以处理泛型类型。 -
GenericToStringSerializer:将对象的
toString()
方法的结果进行序列化,适用于可以通过toString()
表达的简单对象。
再看SpringBoot自动装配中提供的 StringRedisTemplate
Bean对象,就会发现它使用的全部是 StringRedisSerializer
序列化器,它要求调用 RedisTemplate
存储键值对时,数据类型都为 String
,然后在序列化时,直接调用 String
类的getBytes
方法,反序列化时则通过new String(bytes)
方式。
自动装配默认使用的Redis客户端为什么是Lettuce
Spring Boot Starter Redis 默认使用 Lettuce 作为 Redis 客户端,是基于其性能优势、异步与反应式支持、线程安全性、集群与高可用性支持等多方面的优点。关键原因如下:
- Lettuce 的异步与反应式支持:Lettuce可以让应用程序以非阻塞的方式处理 Redis 操作。
- 线程安全:Lettuce 是一个线程安全的 Redis 客户端,允许多个线程共享同一个连接实例进行操作。
- 高可用与集群支持:Lettuce 支持 Redis 集群模式和分片(Sharding),并且能够处理主从复制架构中的故障转移情况,确保应用程序在 Redis 节点故障时仍然能够正常运行。
- 轻量且无第三方依赖:Lettuce 是一个轻量级的客户端,并且不依赖于 Netty 之外的第三方库。
再说 Jedis ,它与 Lettuce 相比具有如下限制:
- 同步 API:Jedis 是一个传统的同步 Redis 客户端,不支持异步操作,因此在处理高并发请求时,性能可能不如 Lettuce。
- 连接池依赖:Jedis 依赖于连接池来管理 Redis 连接,这在一些高并发场景中可能导致性能瓶颈或连接池耗尽的问题。
因此,Lettuce 更适合现代微服务架构和高并发场景,使其成为 Spring Boot 的首选 Redis 客户端。