一、前言:为什么用 Spring Data Redis?
在 Spring Boot 项目中,直接使用 Jedis 或 Lettuce 操作 Redis 虽然灵活,但存在以下问题:
- ❌ 需手动管理连接、异常处理
- ❌ 序列化/反序列化逻辑重复
- ❌ 无法享受 Spring 的依赖注入、AOP、事务等特性
而 Spring Data Redis 作为 Spring 官方提供的 Redis 集成模块,提供了:
✅ 自动配置 (开箱即用)
✅ 统一 API (RedisTemplate / StringRedisTemplate)
✅ 对象序列化支持
✅ Repository 模式 (类似 JPA,操作 Hash)
✅ 与 Spring 生态无缝集成
本文将带你从零搭建 Spring Data Redis 环境,并实现常用操作。
二、环境准备
2.1 前提条件
- JDK 8+
- Spring Boot 2.7+(默认使用 Lettuce)
- Redis 服务(本地或远程)
bash
# 启动本地 Redis(Docker)
docker run -d --name redis -p 6379:6379 redis:7.2
2.2 Maven 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 若需连接池(Lettuce 默认不依赖连接池,但推荐添加) -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
💡 注意 :Spring Boot 2.x+ 默认客户端是 Lettuce(非阻塞、线程安全),而非 Jedis。
三、基础配置:application.yml
spring:
redis:
host: localhost
port: 6379
password: "" # 无密码留空
database: 0
timeout: 2000ms # 连接超时
lettuce:
pool:
max-active: 8 # 最大连接数
max-idle: 8 # 最大空闲连接
min-idle: 0 # 最小空闲连接
max-wait: -1ms # 获取连接最大等待时间(-1 表示无限)
✅ 启动时,Spring Boot 会自动创建
RedisConnectionFactory、RedisTemplate等 Bean。
四、核心组件:RedisTemplate vs StringRedisTemplate
| 组件 | Key/Value 类型 | 适用场景 |
|---|---|---|
RedisTemplate<K, V> |
泛型(Object) | 存储 Java 对象(需配置序列化) |
StringRedisTemplate |
String / String | 存储字符串、JSON、简单 KV |
4.1 使用 StringRedisTemplate(推荐用于简单场景)
java
@Service
public class CacheService {
@Autowired
private StringRedisTemplate stringRedisTemplate;
public void set(String key, String value) {
stringRedisTemplate.opsForValue().set(key, value);
}
public void setEx(String key, String value, long timeout, TimeUnit unit) {
stringRedisTemplate.opsForValue().set(key, value, timeout, unit);
}
public String get(String key) {
return stringRedisTemplate.opsForValue().get(key);
}
// List 操作
public void lpush(String key, String... values) {
stringRedisTemplate.opsForList().leftPushAll(key, values);
}
// Set 操作
public void sadd(String key, String... values) {
stringRedisTemplate.opsForSet().add(key, values);
}
// ZSet 操作
public void zadd(String key, double score, String member) {
stringRedisTemplate.opsForZSet().add(key, member, score);
}
}
4.2 使用 RedisTemplate(存储 Java 对象)
步骤 1:配置序列化方式(避免乱码)
java
@Configuration
@EnableRedisRepositories // 启用 Redis Repository
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 使用 Jackson 序列化
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(mapper);
// 设置 key 和 value 的序列化
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
}
步骤 2:操作对象
java
@Service
public class UserService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
public void saveUser(User user) {
redisTemplate.opsForValue().set("user:" + user.getId(), user, 1, TimeUnit.HOURS);
}
public User getUser(Long id) {
return (User) redisTemplate.opsForValue().get("user:" + id);
}
}
✅ 优势 :自动完成对象 ↔ JSON 转换,无需手动
JSON.toJSONString()
五、高级特性:Redis Repository(操作 Hash)
Spring Data Redis 支持类似 JPA 的 Repository 模式 ,专用于操作 Hash 类型。
5.1 定义实体类
java
@RedisHash("user") // Hash key 前缀
public class User {
@Id
private Long id;
private String name;
private Integer age;
// 构造函数、getter/setter 略
}
5.2 定义 Repository 接口
java
public interface UserRepository extends CrudRepository<User, Long> {
// 自动继承 save(), findById(), delete() 等方法
}
5.3 使用 Repository
java
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public void save(User user) {
userRepository.save(user);
// 实际执行:HSET user:id name "Alice" age 25
}
public Optional<User> findById(Long id) {
return userRepository.findById(id);
}
}
🔍 底层原理:
- Hash key =
user:id- 字段 = 对象属性
- 自动序列化为字符串
⚠️ 注意 :Repository 仅适用于 Hash ,且实体必须有@Id
六、常见操作封装示例
6.1 分布式锁(基于 RedisTemplate)
java
public boolean tryLock(String lockKey, String requestId, int expireSeconds) {
Boolean result = stringRedisTemplate.execute(
(RedisCallback<Boolean>) connection ->
connection.set(lockKey.getBytes(),
requestId.getBytes(),
Expiration.seconds(expireSeconds),
RedisStringCommands.SetOption.SET_IF_ABSENT)
);
return Boolean.TRUE.equals(result);
}
public void unlock(String lockKey, String requestId) {
// 安全解锁需 Lua 脚本(略)
stringRedisTemplate.delete(lockKey);
}
6.2 缓存工具类
java
@Component
public class RedisCache {
@Autowired
private StringRedisTemplate redisTemplate;
public <T> void set(String key, T value, long timeout, TimeUnit unit) {
redisTemplate.opsForValue().set(key, JSON.toJSONString(value), timeout, unit);
}
public <T> T get(String key, Class<T> clazz) {
String json = redisTemplate.opsForValue().get(key);
return json == null ? null : JSON.parseObject(json, clazz);
}
}
七、序列化方案对比
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| JDK 序列化(默认) | 无需配置 | 体积大、跨语言不兼容 | 内部系统 |
| String(JSON) | 可读、通用 | 需手动转换 | Web API、前后端交互 |
| Jackson2Json | 自动对象映射 | 需配置 | 存储 POJO |
| Protobuf | 体积小、高效 | 需定义 schema | 高性能微服务 |
✅ 推荐 :Web 项目优先使用 Jackson2JsonRedisSerializer
八、最佳实践与避坑指南
✅ 最佳实践
- 优先使用
StringRedisTemplate处理字符串、JSON - 对象缓存务必配置序列化,避免 `` 乱码
- key 命名规范 :如
user:{id}:profile - 设置 TTL,防止内存泄漏
- 监控 Redis 内存与连接数
❌ 常见错误
- 未配置序列化 → Redis 中看到
aced0005...(JDK 序列化结果) - 直接存储大对象 → 网络传输慢、内存爆炸
- 忘记加
@EnableRedisRepositories→ Repository 无法注入
九、结语
感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!