1. 添加依赖
在pom.xml
中添加Spring Data Redis依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
- 说明:该依赖集成了Redis客户端(默认使用Lettuce)和
RedisTemplate
工具类。
2. 配置Redis连接信息
在application.yml
中配置Redis服务器信息:
spring:
redis:
host: localhost # Redis服务器地址
port: 6379 # Redis服务器端口
password: yourpassword # Redis密码(如果有)
database: 0 # 使用的数据库索引(0-15)
timeout: 3000ms # 连接超时时间
lettuce: # 使用Lettuce客户端(默认)
pool:
max-active: 8 # 最大连接数
max-wait: -1ms # 最大等待时间
max-idle: 8 # 最大空闲连接
min-idle: 0 # 最小空闲连接
3. 配置RedisTemplate
Spring Boot默认提供了StringRedisTemplate
(键值对为字符串),但通常需要自定义RedisTemplate
以支持对象序列化。
3.1 自定义RedisTemplate配置
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 设置Key的序列化方式
template.setKeySerializer(new StringRedisSerializer());
// 设置Value的序列化方式(JSON格式)
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
// 设置HashKey的序列化方式
template.setHashKeySerializer(new StringRedisSerializer());
// 设置HashValue的序列化方式
template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
template.afterPropertiesSet();
return template;
}
}
- 序列化说明:
StringRedisSerializer
:将键值序列化为字符串。GenericJackson2JsonRedisSerializer
:将对象序列化为JSON格式,支持泛型和复杂对象。
4. RedisTemplate常用操作
RedisTemplate
提供了多种操作接口,对应Redis的不同数据结构。
4.1 操作字符串(String)
@Autowired
private RedisTemplate<String, Object> redisTemplate;
public void operateString() {
// 存储值(永久有效)
redisTemplate.opsForValue().set("name", "张三");
// 存储值(带过期时间)
redisTemplate.opsForValue().set("age", 20, 10, TimeUnit.SECONDS);
// 获取值
String name = (String) redisTemplate.opsForValue().get("name");
Integer age = (Integer) redisTemplate.opsForValue().get("age");
// 递增/递减(适用于数值类型)
redisTemplate.opsForValue().increment("counter", 1);
}
4.2 操作哈希(Hash)
public void operateHash() {
HashOperations<String, String, Object> hashOps = redisTemplate.opsForHash();
// 存储Hash
hashOps.put("user:1", "name", "李四");
hashOps.put("user:1", "age", 25);
// 获取单个字段
String username = (String) hashOps.get("user:1", "name");
// 获取整个Hash
Map<String, Object> user = hashOps.entries("user:1");
// 获取所有字段名和值
Set<String> keys = hashOps.keys("user:1");
List<Object> values = hashOps.values("user:1");
}
4.3 操作列表(List)
public void operateList() {
ListOperations<String, Object> listOps = redisTemplate.opsForList();
// 左插入(栈结构)
listOps.leftPush("tasks", "task1");
listOps.leftPushAll("tasks", "task2", "task3");
// 右插入(队列结构)
listOps.rightPush("tasks", "task4");
// 获取列表范围
List<Object> tasks = listOps.range("tasks", 0, -1);
// 弹出元素
Object task = listOps.leftPop("tasks");
}
4.4 操作集合(Set)
public void operateSet() {
SetOperations<String, Object> setOps = redisTemplate.opsForSet();
// 添加元素
setOps.add("fruits", "apple", "banana", "cherry");
// 获取所有元素
Set<Object> fruits = setOps.members("fruits");
// 判断元素是否存在
boolean exists = setOps.isMember("fruits", "apple");
// 移除元素
setOps.remove("fruits", "banana");
}
4.5 操作有序集合(ZSet)
public void operateZSet() {
ZSetOperations<String, Object> zSetOps = redisTemplate.opsForZSet();
// 添加元素(带分数,用于排序)
zSetOps.add("ranking", "player1", 100);
zSetOps.add("ranking", "player2", 200);
zSetOps.add("ranking", "player3", 150);
// 获取排名(从小到大)
Set<Object> ranking = zSetOps.range("ranking", 0, -1);
// 获取分数
Double score = zSetOps.score("ranking", "player2");
// 增加分数
zSetOps.incrementScore("ranking", "player1", 50);
}
5. 高级功能
5.1 事务操作
public void transactionExample() {
redisTemplate.execute(new SessionCallback<Object>() {
@Override
public <K, V> Object execute(RedisOperations<K, V> operations) throws DataAccessException {
operations.multi(); // 开启事务
operations.opsForValue().set((K) "tx-key1", (V) "value1");
operations.opsForValue().set((K) "tx-key2", (V) "value2");
return operations.exec(); // 执行事务
}
});
}
5.2 管道操作(批量执行)
public void pipelineExample() {
List<Object> results = redisTemplate.executePipelined(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection) throws DataAccessException {
StringRedisConnection stringConn = (StringRedisConnection) connection;
for (int i = 0; i < 1000; i++) {
stringConn.set("key:" + i, "value:" + i);
}
return null;
}
});
}
5.3 发布订阅
// 发布消息
public void publishMessage(String channel, String message) {
redisTemplate.convertAndSend(channel, message);
}
// 订阅消息(需配置Listener)
@Component
public class RedisMessageListener implements MessageListener {
@Override
public void onMessage(Message message, byte[] pattern) {
String channel = new String(message.getChannel());
String content = new String(message.getBody());
System.out.println("收到消息: " + content + " from channel: " + channel);
}
}
5.4 分布式锁
public void distributedLockExample() {
String lockKey = "resource-lock";
Boolean locked = redisTemplate.opsForValue().setIfAbsent(
lockKey, "locked", 30, TimeUnit.SECONDS); // 原子操作
if (locked) {
try {
// 执行需要加锁的业务逻辑
} finally {
redisTemplate.delete(lockKey); // 释放锁
}
}
}
6. 对象序列化与反序列化
存储自定义对象时,确保对象实现Serializable
接口,并使用JSON序列化:
6.1 实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private String id;
private String name;
private Integer age;
}
6.2 存储和读取对象
public void saveAndGetUser() {
User user = new User("1", "王五", 30);
// 存储对象
redisTemplate.opsForValue().set("user:1", user);
// 读取对象
User result = (User) redisTemplate.opsForValue().get("user:1");
}
7. 常见问题与优化
7.1 序列化性能问题
- JSON序列化比JDK原生序列化更高效,但需注意循环引用问题。
- 对性能敏感的场景,可使用
Protostuff
或Kryo
替代JSON序列化。
7.2 连接池配置
spring:
redis:
lettuce:
pool:
max-active: 100 # 最大连接数
max-wait: 1000ms # 获取连接的最大等待时间
max-idle: 20 # 最大空闲连接
min-idle: 5 # 最小空闲连接
7.3 异常处理
try {
// Redis操作
} catch (RedisConnectionFailureException e) {
// 处理连接失败
log.error("Redis连接失败", e);
} catch (RedisSystemException e) {
// 处理系统异常
log.error("Redis系统异常", e);
}
8. 与缓存注解结合(@Cacheable)
Spring Cache抽象提供了@Cacheable
、@CacheEvict
等注解,可与Redis集成:
@Service
public class UserService {
@Cacheable(value = "users", key = "#id")
public User getUser(String id) {
// 从数据库查询
return userRepository.findById(id);
}
@CacheEvict(value = "users", key = "#id")
public void deleteUser(String id) {
// 删除用户
userRepository.deleteById(id);
}
}