Spring Data Redis 是 Spring 生态中操作 Redis 的核心模块,它封装了 Redis 客户端的底层细节(如 Jedis 或 Lettuce),提供了统一的 API 来操作 Redis 的数据结构。以下是详细实现步骤:
在 pom.xml
中添加依赖(以 Spring Boot 3.x 为例):
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
<dependency>
<groupId>io.lettucegroupId>
<artifactId>lettuce-coreartifactId>
dependency>
<dependency>
<groupId>org.apache.commonsgroupId>
<artifactId>commons-pool2artifactId>
dependency>
在 application.yml
中配置 Redis 服务器信息:
spring:
redis:
host: localhost # Redis 服务器地址
port: 6379 # 默认端口
password: 123456 # 密码(若无则省略)
database: 0 # 默认数据库索引
lettuce:
pool:
max-active: 8 # 最大连接数
max-idle: 4 # 最大空闲连接
min-idle: 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(RedisSerializer.string());
template.setHashKeySerializer(RedisSerializer.string());
// Value 统一使用 JSON 序列化
Jackson2JsonRedisSerializer<Object> jsonSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
template.setValueSerializer(jsonSerializer);
template.setHashValueSerializer(jsonSerializer);
// 特殊数据结构的 Value 序列化(根据需求覆盖)
// template.setDefaultSerializer(jsonSerializer); // 可选:全局默认序列化
template.afterPropertiesSet();
return template;
}
}
opsForValue()
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// 写入值
redisTemplate.opsForValue().set("user:1:name", "Alice");
// 读取值
String name = (String) redisTemplate.opsForValue().get("user:1:name");
// 原子递增
Long count = redisTemplate.opsForValue().increment("article:100:views");
opsForHash()
// 存储用户对象
Map<String, String> user = new HashMap<>();
user.put("name", "Bob");
user.put("age", "25");
redisTemplate.opsForHash().putAll("user:2", user);
// 获取单个字段
String age = (String) redisTemplate.opsForHash().get("user:2", "age");
// 更新字段
redisTemplate.opsForHash().put("user:2", "age", "26");
// 获取所有字段
Map<Object, Object> userData = redisTemplate.opsForHash().entries("user:2");
opsForList()
// 左侧插入元素
redisTemplate.opsForList().leftPush("task:queue", "task1");
// 右侧弹出元素(阻塞式)
String task = (String) redisTemplate.opsForList().rightPop("task:queue", 10, TimeUnit.SECONDS);
// 获取列表范围
List<Object> tasks = redisTemplate.opsForList().range("task:queue", 0, -1);
opsForSet()
// 添加元素
redisTemplate.opsForSet().add("article:100:tags", "tech", "java", "spring");
// 判断元素是否存在
boolean exists = redisTemplate.opsForSet().isMember("article:100:tags", "java");
// 求交集
Set<Object> commonTags = redisTemplate.opsForSet().intersect("article:100:tags", "article:101:tags");
opsForZSet()
// 添加元素及分数
redisTemplate.opsForZSet().add("leaderboard", "player1", 100.0);
redisTemplate.opsForZSet().add("leaderboard", "player2", 85.5);
// 获取前 10 名
Set<ZSetOperations.TypedTuple<Object>> topPlayers =
redisTemplate.opsForZSet().reverseRangeWithScores("leaderboard", 0, 9);
// 更新分数
redisTemplate.opsForZSet().incrementScore("leaderboard", "player1", 20.0);
opsForHyperLogLog()
// 添加元素
redisTemplate.opsForHyperLogLog().add("uv:20231001", "user1", "user2", "user3");
// 统计基数
Long uv = redisTemplate.opsForHyperLogLog().size("uv:20231001");
opsForValue().setBit()
// 设置第 5 位为 1(表示用户 ID=5 已签到)
redisTemplate.opsForValue().setBit("sign:user:202310", 5, true);
// 统计总签到数
Long count = redisTemplate.execute(
(RedisCallback<Long>) conn -> conn.bitCount("sign:user:202310".getBytes())
);
opsForGeo()
// 添加地理位置
redisTemplate.opsForGeo().add("cities",
new Point(116.405285, 39.904989), "Beijing");
// 查询距离
Distance distance = redisTemplate.opsForGeo()
.distance("cities", "Beijing", "Shanghai", Metrics.KILOMETERS);
// 附近 100km 内的城市
GeoResults<GeoLocation<Object>> results = redisTemplate.opsForGeo()
.radius("cities", "Beijing", new Distance(100, Metrics.KILOMETERS));
redisTemplate.execute(new SessionCallback<List<Object>>() {
@Override
public List<Object> execute(RedisOperations operations) {
operations.multi(); // 开启事务
operations.opsForValue().set("key1", "value1");
operations.opsForHash().put("hash1", "field", "value");
return operations.exec(); // 提交事务
}
});
// 发布消息
redisTemplate.convertAndSend("news", "Breaking news: Spring 6 released!");
// 订阅消息(需定义 MessageListener)
@Bean
public MessageListenerAdapter listenerAdapter(MessageReceiver receiver) {
return new MessageListenerAdapter(receiver, "receiveMessage");
}
@Bean
public RedisMessageListenerContainer container(RedisConnectionFactory factory,
MessageListenerAdapter listener) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(factory);
container.addMessageListener(listener, new ChannelTopic("news"));
return container;
}
List<Object> results = redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
connection.stringCommands().set("key1".getBytes(), "value1".getBytes());
connection.stringCommands().set("key2".getBytes(), "value2".getBytes());
return null;
});
@SpringBootTest
public class RedisTest {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Test
void testString() {
redisTemplate.opsForValue().set("testKey", "Hello Redis");
assertEquals("Hello Redis", redisTemplate.opsForValue().get("testKey"));
}
}
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Test
void testConnection() {
RedisConnection conn = redisConnectionFactory.getConnection();
assertTrue(conn.ping().equals("PONG"));
conn.close();
}
序列化一致性
确保所有操作的 Key/Value 序列化方式一致,避免出现乱码或类型错误。
连接泄漏
使用 @Transactional
或手动关闭连接,避免未释放的连接耗尽资源。
数据淘汰策略
在 Redis 配置中设置 maxmemory-policy
(如 allkeys-lru
),防止内存溢出。
集群模式
若使用 Redis 集群,需在配置中指定所有节点地址:
spring:
redis:
cluster:
nodes: host1:6379,host2:6379,host3:6379