SpringBoot集成Redis的教程网上很多,总体来说就是三个步骤:添加依赖、修改配置文件、自定义Redis配置类(自定义序列化器),具体步骤可自行搜索,本文主要解惑集成中的常见疑问。
1,选择什么依赖?
SpringBoot集成Redis共有三种依赖可选:spring-boot-starter-data-redis,spring-data-redis,redisson-spring-boot-start。先说结果:
优先选择 spring-boot-starter-data-redis,快速实现缓存功能,避免过度设计。
高并发或分布式系统,直接使用 redisson-spring-boot-starter,其内置的分布式锁、限流器可显著降低复杂度。
1),spring-boot-starter-data-redis(官方推荐)
定位:Spring Boot官方提供的开箱即用方案,封装了Spring Data Redis的核心功能。
底层客户端:默认使用Lettuce(基于Netty的非阻塞I/O),也可切换为Jedis(传统阻塞式I/O)。
核心优势:
自动化配置:仅需配置spring.redis.host/port等参数即可自动初始化连接池和RedisTemplate。
统一操作接口:提供RedisTemplate和StringRedisTemplate,支持字符串、哈希、列表等数据结构操作。
与Spring生态无缝集成:支持Spring Cache抽象、事务管理和Repository模式。
局限性:
高级功能(如分布式锁、限流)需自行实现(如Lua脚本或第三方库)。
默认序列化方式为JDK序列化(可读性差),需手动配置JSON序列化。
适用场景:简单缓存、基础数据操作
性能:中等(依赖Lettuce/Jedis)
高级功能:需自行实现
2),spring-data-redis
非SpringBoot项目(如Springmvc,Spring)引入的依赖,不包含客户端、连接池,需手动配置连接工厂。spring-boot-starter-data-redis已包含 spring-data-redis。
3),redisson-spring-boot-start(分布式redis依赖)
定位:Redisson提供的增强方案,支持分布式对象和高级分布式功能。
核心优势:
开箱即用的分布式工具:内置分布式锁(支持自动续期)、信号量、限流器(RRateLimiter)、延迟队列等。
高性能本地缓存:通过RLocalCachedMap减少网络IO,缓存命中率提升显著(压测可达百万级QPS)。
异步与响应式支持:基于Netty的非阻塞通信,支持RBatch批量操作提升吞吐量。
局限性:
学习成本高,需理解分布式对象(如RMap、RBucket)的API设计。
部分简单操作(如基础字符串存取)代码量略多于RedisTemplate。
适用场景:分布式锁、限流、高并发系统
性能:高于spring-boot-starter-data-redis,基于Netty异步+本地缓存优化
高级功能:内置分布式工具
2,多模块怎么将Redis配置文件和配置类独立出来,避免各模块重复工作?
- 微服务系统可将做配置中心;
- 非微服务系统可设置一个base-module模块,在需要使用redis的模块的pom文件中引入该模块的依赖。
3,为什么要配置Redis连接池,其作用是什么,有哪些连接池可选?
Redis连接池(Pool)是指客户端连接池,是为了管理客户端(如Jedis或Lettuce)与Redis服务器之间的网络连接而存在的。
Redis服务端可简单理解成单线程应用(实际非单线程,参考文章Redis-02 单线程与高性能-CSDN博客),无连接池一说。
Redis客户端(即自己的程序,是多线程的)通常是Springboot应用,是多线程的web服务,可同时处理上万用户请求,可能产生并发的Redis操作请求,配置客户端连接池,可在客户端请求Redis时,减少客户端连接Redis服务器带来的创建、销毁等开销(如建立tcp连接、tcp断开、认证等)。
4,RedisTemplate和StringRedisTemplate是什么,有什么区别,生产环境一般怎么使用?
科普:
它们都是Spring Data Redis提供的核心工具类,用于在Java应用中与Redis服务器进行交互,封装了底层的连接管理、序列化/反序列化等复杂操作,让你可以用面向对象的方式操作Redis。
区别:
核心的区别是默认的序列化器不同。序列化器决定了Java对象如何转换成二进制数据存入Redis,以及如何从二进制数据变回Java对象。可以把 StringRedisTemplate 看作是 RedisTemplate<String, String> 的一个特例,它强制要求键和值都是字符串,并使用字符串序列化器。
StringRedisTeplate | RedisTeplate | |
---|---|---|
key序列化器 | StringRedisSerializer | JdkSerializationRedisSerializer |
value序列化器 | StringRedisSerializer | JdkSerializationRedisSerializer |
存储结果 | 可读的字符串。set("name", "Alice") 在Redis中存的就是 "Alice" | 不可读的JDK序列化字节码。存进去是乱码,如 \xac\xed\x00\x05t\x00\x04name |
使用场景 | 处理字符串和文本结构的数据 | 处理复杂的Java对象(但需要配置序列化器) |
生产环境怎么使用:
优先使用 StringRedisTemplate 来处理字符串键值对。
对于需要存储复杂Java对象的场景,会配置一个专门化的 RedisTemplate(例如 RedisTemplate<String, Object>),并将其值的序列化器改为JSON序列化器(如 Jackson2JsonRedisSerializer 或 GenericJackson2JsonRedisSerializer)。
绝对要避免使用默认配置(JDK序列化)的 RedisTemplate!
5,生产环境怎么设置RedisTemplate的序列化器?
以常用的GenericJackson2JsonRedisSerializer序列化器为例,生产环境各种配置方式如下:
1),简单快速使用设置
@Configuration
public class RedisTemplateConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(connectionFactory);// 设置Key和HashKey的序列化器为StringRedisSerializertemplate.setKeySerializer(new StringRedisSerializer());template.setHashKeySerializer(new StringRedisSerializer());// 设置Value和HashValue的序列化器为GenericJackson2JsonRedisSerializer (JSON格式)GenericJackson2JsonRedisSerializer jsonSerializer = new GenericJackson2JsonRedisSerializer();template.setValueSerializer(jsonSerializer);template.setHashValueSerializer(jsonSerializer);template.afterPropertiesSet();return template;}}
上述序列化器设置完成即可使用Redis,但是有个弊端,假如存放的是对象,如User(id, name, age, sex, position),在Redis中是Json数据格式,web端获取User时,返回的是LinkedHashMap<String, Object>,无法直接强转成User对象。同样,如果存放的是List<User>,在Redis中是Json数组,返回则是List<LinkedHashMap>。
2),优化序列化设置
@Configuration
public class RedisTemplateConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(connectionFactory);// 设置Key和HashKey的序列化器为StringRedisSerializertemplate.setKeySerializer(new StringRedisSerializer());template.setHashKeySerializer(new StringRedisSerializer());// 设置Value和HashValue的序列化器为GenericJackson2JsonRedisSerializer (JSON格式),并配置返回序列化类型// 创建 ObjectMapper 并配置多态类型支持/*** 作用:* 这行代码配置 ObjectMapper 在序列化 JSON 时,自动嵌入类的类型信息。* 这样在反序列化时,Jackson 就能根据这些信息准确地还原成原始对象类型,而不是简单的 LinkedHashMap。*/ObjectMapper objectMapper = new ObjectMapper();objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, // 非严格验证,更严谨的使用方式是将类型验证器LaissezFaireSubTypeValidator替换为TypeValidatorObjectMapper.DefaultTyping.NON_FINAL,JsonTypeInfo.As.PROPERTY);GenericJackson2JsonRedisSerializer jsonSerializer = new GenericJackson2JsonRedisSerializer(objectMapper);template.setValueSerializer(jsonSerializer);template.setHashValueSerializer(jsonSerializer);template.afterPropertiesSet();return template;}}
如上述代码,多添加了ObjectMapper,并激活了如下几个配置:
- LaissezFaireSubTypeValidator.instance:配置了对象的类型验证器,允许反序列化任何类型(有安全风险,但操作简单方便开发)。
- ObjectMapper.DefaultTyping.NON_FINAL:指定哪些类型需要包含类型信息。NON_FINAL:所有非final类都需要包含类型信息。可选项还有:NON_CONCRETE_AND_ARRAYS(非具体类型和数组), EVERYTHING(所有类型)
- JsonTypeInfo.As.PROPERTY:指定类型在Redis中如何潜入到JSON里。PROPERTY:作为单独属性添加到JSON中。可选项还有:WRAPPER_ARRAY(包装为数组),WRAPPER_OBJECT(包装为对象)。
添加如上反序列化配置后,假如存放的是List<User>,则Redis中存储格式如下:
["java.util.ArrayList",[["com.example.User",{"id":1,"name":"张三"}],["com.example.User", {"id":2,"name":"李四"}]]
]
客户端获取数据时,反序列化就知道该对象是List,内部对象是User,这样结果就可以直接强转。
3),反序列化类型验证器
package com.mango.basedata.common;import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.BasicPolymorphicTypeValidator;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;@Configuration
public class RedisTemplateConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(connectionFactory);// 设置Key和HashKey的序列化器为StringRedisSerializertemplate.setKeySerializer(new StringRedisSerializer());template.setHashKeySerializer(new StringRedisSerializer());// 设置Value和HashValue的序列化器为GenericJackson2JsonRedisSerializer (JSON格式),并配置返回序列化类型// 创建 ObjectMapper 并配置多态类型支持/*** 作用:* 这行代码配置 ObjectMapper 在序列化 JSON 时,自动嵌入类的类型信息。* 这样在反序列化时,Jackson 就能根据这些信息准确地还原成原始对象类型,而不是简单的 LinkedHashMap。*/ObjectMapper objectMapper = new ObjectMapper();// 创建更安全的类型验证器(白名单机制)BasicPolymorphicTypeValidator typeValidator = BasicPolymorphicTypeValidator.builder().allowIfSubType("com.example.models.entity").allowIfSubType("java.util.ArrayList").allowIfSubType("java.util.HashMap").build();objectMapper.activateDefaultTyping(typeValidator,ObjectMapper.DefaultTyping.NON_FINAL,JsonTypeInfo.As.PROPERTY);GenericJackson2JsonRedisSerializer jsonSerializer = new GenericJackson2JsonRedisSerializer(objectMapper);template.setValueSerializer(jsonSerializer);template.setHashValueSerializer(jsonSerializer);template.afterPropertiesSet();return template;}}