第五章:Redis 的 Java 客户端
📺 对应集数:p016p023(第1522集)
第五章:Redis 的 Java 客户端
5.1 三大 Java 客户端对比
| 客户端 | 特点 | 适用场景 |
|---|---|---|
| Jedis | 方法名 = Redis 命令名,学习成本低;线程不安全,需用连接池 | 简单使用,快速上手 |
| Lettuce | 基于 Netty,支持同步/异步/响应式编程;线程安全;Spring 默认使用 | Spring 生态,响应式编程 |
| Redisson | 基于 Redis 实现分布式工具类(分布式锁、Map、队列等) | 分布式环境下的工具需求 |
5.2 Jedis 快速入门
引入依赖
xml
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.7.0</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
基本使用(4 步)
java
public class JedisTest {
private Jedis jedis;
@BeforeEach
void setUp() {
// 第1步:建立连接
jedis = new Jedis("192.168.150.101", 6379);
// 设置密码
jedis.auth("123321");
// 选择数据库
jedis.select(0);
}
@Test
void testString() {
// 第2步:操作数据(方法名 = 命令名)
jedis.set("name", "虎哥");
String result = jedis.get("name");
System.out.println("result = " + result);
}
@Test
void testHash() {
jedis.hset("user:1", "name", "Jack");
jedis.hset("user:1", "age", "21");
Map<String, String> map = jedis.hgetAll("user:1");
System.out.println(map);
}
@AfterEach
void tearDown() {
// 第3步:释放资源
if (jedis != null) {
jedis.close();
}
}
}
Jedis 连接池
java
public class JedisConnectionFactory {
private static final JedisPool jedisPool;
static {
// 配置连接池
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(8); // 最大连接数
config.setMaxIdle(8); // 最大空闲连接
config.setMinIdle(0); // 最小空闲连接
config.setMaxWaitMillis(1000); // 等待时长(毫秒)
// 创建连接池
jedisPool = new JedisPool(config, "192.168.150.101", 6379, 1000, "123321");
}
// 获取 Jedis 对象
public static Jedis getJedis() {
return jedisPool.getResource();
}
}
// 使用方式
@Test
void testPool() {
Jedis jedis = JedisConnectionFactory.getJedis();
jedis.set("name", "虎哥");
System.out.println(jedis.get("name"));
jedis.close(); // 底层不会真的关闭,而是归还到连接池
}
5.3 Spring Data Redis
简介
- Spring Data 是 Spring 中数据操作的统一模块
- Spring Data Redis 对 Jedis 和 Lettuce 进行了整合
- 提供
RedisTemplate作为统一的操作 API - 支持自动序列化/反序列化(JDK、JSON 等)
- 支持 Redis 的发布订阅、哨兵、集群等高级功能
RedisTemplate 的设计
java
// RedisTemplate 提供了分组操作 API
RedisTemplate.opsForValue() // → String 类型操作
RedisTemplate.opsForHash() // → Hash 类型操作
RedisTemplate.opsForList() // → List 类型操作
RedisTemplate.opsForSet() // → Set 类型操作
RedisTemplate.opsForZSet() // → SortedSet 类型操作
快速入门
引入依赖:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
配置文件(application.yml):
yaml
spring:
redis:
host: 192.168.150.101
port: 6379
password: 123321
database: 0
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0
max-wait: 1000ms
注入使用:
java
@SpringBootTest
class RedisTemplateTest {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Test
void testString() {
// 获取 Value 操作对象
redisTemplate.opsForValue().set("name", "虎哥");
Object name = redisTemplate.opsForValue().get("name");
System.out.println(name);
}
}
5.4 RedisTemplate 的序列化问题
默认序列化的问题
RedisTemplate 默认使用 JDK 序列化(JdkSerializationRedisSerializer),会导致:
- 可读性差:数据在 Redis 中变成二进制乱码
- 内存占用大:包含额外的类信息
方案一:自定义 RedisTemplate(自动 JSON 序列化)
java
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// Key 和 HashKey 使用 String 序列化
StringRedisSerializer stringSerializer = new StringRedisSerializer();
template.setKeySerializer(stringSerializer);
template.setHashKeySerializer(stringSerializer);
// Value 和 HashValue 使用 JSON 序列化
GenericJackson2JsonRedisSerializer jsonSerializer = new GenericJackson2JsonRedisSerializer();
template.setValueSerializer(jsonSerializer);
template.setHashValueSerializer(jsonSerializer);
return template;
}
}
优点 :自动序列化/反序列化,代码简洁
缺点:JSON 中会携带 Java 类型信息(@class 字段),占用额外空间
方案二:使用 StringRedisTemplate(手动 JSON 序列化)⭐推荐
java
@SpringBootTest
class StringRedisTemplateTest {
@Autowired
private StringRedisTemplate stringRedisTemplate;
// JSON 工具
private static final ObjectMapper mapper = new ObjectMapper();
@Test
void testSaveUser() throws JsonProcessingException {
// 创建对象
User user = new User("虎哥", 21);
// 手动序列化为 JSON 字符串
String json = mapper.writeValueAsString(user);
// 存入 Redis
stringRedisTemplate.opsForValue().set("user:200", json);
}
@Test
void testGetUser() throws JsonProcessingException {
// 从 Redis 获取 JSON 字符串
String json = stringRedisTemplate.opsForValue().get("user:200");
// 手动反序列化为对象
User user = mapper.readValue(json, User.class);
System.out.println(user);
}
}
优点 :Redis 中数据简洁干净,节省存储空间
缺点:需要手动序列化/反序列化(可封装工具类)
两种序列化方案对比
| 对比项 | 自定义 RedisTemplate | StringRedisTemplate |
|---|---|---|
| 序列化方式 | 自动 JSON 序列化 | 需手动 JSON 序列化 |
| Redis 中存储 | JSON + 类型信息 | 纯 JSON |
| 代码复杂度 | 配置简单 | 需手动处理序列化 |
| 内存占用 | 较大(含 @class) | 较小(纯数据) |
| 推荐程度 | ⭐⭐⭐ | ⭐⭐⭐⭐ |
5.5 RedisTemplate 操作 Hash 类型
java
@SpringBootTest
class HashTest {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
void testHash() {
// 添加单个字段(HSET → put)
stringRedisTemplate.opsForHash().put("user:400", "name", "虎哥");
stringRedisTemplate.opsForHash().put("user:400", "age", "21");
// 获取单个字段(HGET → get)
Object name = stringRedisTemplate.opsForHash().get("user:400", "name");
System.out.println(name);
// 获取所有键值对(HGETALL → entries)
Map<Object, Object> entries = stringRedisTemplate.opsForHash().entries("user:400");
System.out.println(entries);
// 获取所有 key(HKEYS → keys)
Set<Object> keys = stringRedisTemplate.opsForHash().keys("user:400");
System.out.println(keys);
// 获取所有 value(HVALS → values)
List<Object> values = stringRedisTemplate.opsForHash().values("user:400");
System.out.println(values);
}
}
注意 :Spring Data Redis 的方法名不同于 Redis 命令名,更接近 Java 编程习惯(如 put 对应 HSET)。