一、Redis的Java客户端
1. Jedis
Jedis
以Redis
命令作为方法名称,学习成本低,简单实用。但是Jedis
实例是线程不安全的,多线程环境下需要基于连接池来使用。
2. lettuce【spring官方默认兼容】
Lettuce
是基于Netty
实现的,支持同步、异步和响应式编程方式,并且是线程安全的。支持Redis
的哨兵模式、集群模式和管道模式。
3.Redisson
Redisson
是一个基于Redis
实现的分布式、可伸缩的Java
数据结构集合。包含了诸如Map
、Queue
、Lock
、Semaphore
、AtomicLong
等强大功能。
二、Jedis
2.1 Jedis快速入门
- 引入依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.7.0</version>
</dependency>
- 建立连接
@BeforeEach
void setUp(){
// 1.建立连接
jedis = new Jedis("192.168.0.3", 6379);
// 2.选择库
jedis.select(0);
}
- 测试string
@Test
void testString(){
// 存入数据
String result = jedis.set("name", "lwz");
System.out.println("result = " + result);
// 获取数据
String name = jedis.get("name");
System.out.println("name = " + name);
}
- 释放资源
@AfterEach
void tearDown(){
if(jedis != null){
jedis.close();
}
}
执行结果:
2.2 Jedis连接池
Jedis本身是线程不安全的,并且频繁的创建和销毁连接会有性能损耗,因此推荐使用Jedis连接池代替Jedis的直连方式。
创建Jedis连接池工具类:
public class JedisConnectionFactory {
private static final JedisPool jedisPool;
static{
// 配置连接池
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(8); // 最大连接数
poolConfig.setMaxIdle(8); // 最大空闲连接
poolConfig.setMinIdle(0); // 最小空闲连接
poolConfig.setMaxWaitMillis(1000);
// 创建连接池对象
jedisPool = new JedisPool(poolConfig,
"localhost", 6379, 1000);
}
public static Jedis getJedis(){
return jedisPool.getResource();
}
}
调用连接池:
jedis = JedisConnectionFactory.getJedis();
三、SpringDataRedis
3.1 简介
SpringData
是Spring
中数据操作的模块,包含对各种数据库的集成,其中对Redis
的集成模块就叫做SpringDataRedis
。有如下特点:
- 提供了对不同
Redis
客户端的整合(Lettuce
和Jedis
) - 提供了
RedisTemplate
统一API
来操作Redis
- 支持
Redis
的发布订阅模型 - 支持
Redis
哨兵和Redis
集群 - 支持基于
Lettuce
的响应式编程 - 支持基于
JDK
、JSON
、字符串
、Spring对象
的数据序列化及反序列化 - 支持基于
Redis
的JDKCollection
实现
3.2 API
SpringDataRedis
中提供了RedisTemplate
工具类,其中封装了各种对Redis
的操作。并且将不同数据类型的操作API
封装到了不同的类型中:
API | 返回值类型 | 说明 |
---|---|---|
redisTemplate.opsForValue() | ValueOperations | 操作String类型数据 |
redisTemplate.opsForHash() | HashOperations | 操作Hash类型数据 |
redisTemplate.opsForList() | ListOperations | 操作List类型数据 |
redisTemplate.opsForSet() | SetOperations | 操作Set类型数据 |
redisTemplate.opsForZSet() | ZSetOperations | 操作SortedSet类型数据 |
redisTemplate | 通用的命令 |
3.3 SpringDataRedis 入门
- 引入依赖:
<!--redis依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--common-pool-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
- 在application.yml配置redis信息
spring:
data:
redis:
host: localhost
port: 6379
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0
max-wait: 100ms
- 注入并使用RedisTemplate
@SpringBootTest
class RedisDemoApplicationTests {
@Autowired
private RedisTemplate redisTemplate;
@Test
void testString() {
// 写入一条String数据
redisTemplate.opsForValue().set("name", "lwz");
// 获取String数据
Object name = redisTemplate.opsForValue().get("name");
System.out.println("name = " + name);
}
}
3.4 SpringDataRedis的序列化方式
RedisTemplate可以接收任意Object作为值写入Redis,只不过写入前会把Object序列化为字节形式,默认采用JDK序列化,得到的结果是这样的:
缺点:可读性差、内存占用较大。
我们可以自定义RedisTemplate的序列化方式,代码如下:
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){
// 创建RedisTemplate对象
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 设置连接工厂
template.setConnectionFactory(connectionFactory);
// 创建JSON序列化工具
GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
// 设置Key的序列化
template.setKeySerializer(RedisSerializer.string());
template.setHashKeySerializer(RedisSerializer.string());
// 设置Value的序列化
template.setValueSerializer(jsonRedisSerializer);
template.setHashValueSerializer(jsonRedisSerializer);
// 返回
return template;
}
}
测试:
@Test
void testString() {
// 写入一条String数据
redisTemplate.opsForValue().set("name", "lwz");
// 获取String数据
Object name = redisTemplate.opsForValue().get("name");
System.out.println("name = " + name);
}
结果:
3.5 StringRedisTemplate
Spring默认提供了一个StringRedisTemplate类,它的key和value的序列化方式默认就是String方式。省去了自定义RedisTemplate的过程:
private static final ObjectMapper mapper = new ObjectMapper();
@Test
void testSaveUser() throws JsonProcessingException {
// 创建对象
User user = new User("lwz", 20);
// 手动序列化
String json = mapper.writeValueAsString(user);
// 写入数据
stringRedisTemplate.opsForValue().set("user:2", json);
// 获取数据
String jsonUser = stringRedisTemplate.opsForValue().get("user:2");
// 手动反序列化
User user1 = mapper.readValue(jsonUser, User.class);
System.out.println("user1 = " + user1);
}