Redis的Java客户端
在Redis官网中提供了各种语言的客户端,地址:https://redis.io/clients
常用的客户端
- Jedis:Jedis实例是线程不安全的,多线程环境下需要基于连接池来使用
- Lettuce: 基于Netty实现,支持同步、异步、响应式编程,并且是线程安全的。支持哨兵模式、集群模式、管道模式
- Redisson:基于Redis实现的可伸缩、分布式的java数据结构集合,包含Map、Queue等,而且支持跨进程的同步机制:Lock、Semaphore等待
Jedis客户端
Jedis是一款Java操作Redis数据库的工具,需要注意的是Jedis是线程不安全的,在多线程下使用需要搭配连接池保证每个Jedis实例都有一个连接。
jedis官网:https://github.com/redis/jedis
快速入门:
(1)引入依赖
<!--jedis依赖-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.7.0</version>
</dependency>
<!--junit依赖-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.7.0</version>
<scope>test</scope>
</dependency>
(2)使用
- 普通使用代码示例
package com.hhxy.jedis;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import redis.clients.jedis.Jedis;
public class JedisTest {
private Jedis jedis;
@BeforeEach //这个注解表示,在当前类运行时先运行这个方法
public void setUp(){
// 建立连接
jedis = new Jedis("192.168.88.130",6379);
// 设置密码
jedis.auth("32345678");
// 选择库(不写默认是0号库)
jedis.select(0);
}
@Test
public void testString(){
// 存储String类型的数据
String result = jedis.set("name", "张三");
System.out.println("result = " + result);
// 取数据
String name = jedis.get("name");
System.out.println("name = " + name);
}
@Test
public void testDown(){
if(jedis != null){
jedis.close();
}
}
}
-
jedis连接池
1.编写连接池工具类
public class JedisConnectionFactory { private static JedisPool jedisPool; static { // 配置连接池 JedisPoolConfig poolConfig = new JedisPoolConfig(); poolConfig.setMaxTotal(8); poolConfig.setMaxIdle(8); poolConfig.setMinIdle(0); poolConfig.setMaxWaitMillis(1000); // 创建连接池对象,参数:连接池配置、服务端ip、服务端端口、超时时间、密码 jedisPool = new JedisPool(poolConfig, "192.168.150.101", 6379, 1000, "123321"); } public static Jedis getJedis(){ return jedisPool.getResource(); } }
2.创建连接并使用
Jedis = JedisConnectionFactory.getJedis(); jedis.auth("123456"); jedis.select(0); jedis.set("name","张三"); jedis.close();
SpringDataRedis客户端
SpringData是Spring中数据操作的模块,包含对各种数据库的集成,其中对Redis的集成模块就叫做SpringDataRedis,官网地址:https://spring.io/projects/spring-data-redis
- 提供了对不同Redis客户端的整合Lettuce和Jedis(默认使用的是Lettuce)
- 提供了RedisTemplate统一API来操作Redis
- 支持Redis的发布订阅模型
- 支持Redis哨兵和Redis集群
- 支持基于Lettuce的响应式编程
- 支持基于JDK、JSON、字符串、Spring对象的数据序列化及反序列化
- 支持基于Redis的JDKCollection实现(基于Redis重新实现了java集合)
RedisTemplate
快速入门
(1)引入依赖
在创建SpringBoot项目时,记得要勾选SpringData,不然需要手动导入springdata-starter依赖
<!--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>
(2)配置(新版需要加data层级)
spring:
redis:
host: 192.168.150.101
port: 6379
password: 123321
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0
max-wait: 100ms
(3)注入RedisTemplate使用
@SpringBootTest
class SpringbootSpringdateRedisApplicationTests {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testString(){
// 存入String类型的数据
redisTemplate.opsForValue().set("name","ghp");
// 获取存入的数据
Object name = redisTemplate.opsForValue().get("name");
System.out.println("name = " + name);
}
}
自定义序列化
RedisTemplate默认使用的是JDK的序列化器,可读性差且占用内存较大.存储中文示例:
因为RedisTemplate
默认采用了JDK序列化器的缘故,本质还是由于ObjectOutputStream,为了避免上面情况的发生,我们需要改变RedisTemplate的序列化方式(也就是不使用默认的序列化方式),这意味着我们需要重新定义一个RedisTemplate。
-
(1)导入依赖
<!--SpringBoot整合SpringDataRedis对应的Starter--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!--Redis连接池依赖--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> <!--Jackson依赖--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency>
(2)加配置
@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的序列化(String) template.setKeySerializer(RedisSerializer.string()); template.setHashKeySerializer(RedisSerializer.string()); // 设置Value的序列化 (Json) template.setValueSerializer(jsonRedisSerializer); template.setHashValueSerializer(jsonRedisSerializer); // 返回 return template; } }
整体可读性有了很大提升,并且能将Java对象自动的序列化为JSON字符串,并且查询时能自动把JSON反序列化为Java对象。不过,其中记录了序列化时对应的class名称
,目的是为了查询时实现自动反序列化。这会带来额外的内存开销。
StringRedisTemplate
为了反序列化时知道对象的类型,JSON序列化器会将类的class类型写入JSON结果中,同时存入Redis中,这样会一定程度带来额外的内存开销为了。节省内存空间,就不能使用JSON序列化器来处理Value,而是统一使用String序列化器,这样就只能存String类型的key和value,而面对Object类型的value时,就手动完成对象的序列化和反序列化。
StringRedisTemplate
是RedisTemplate
的子类,它的key和value的序列化方式默认就是String方式,当需要存取Java对象时,手动完成对象的序列化和反序列化
package com.hhxy.redis;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hhxy.redis.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;
@SpringBootTest
public class RedisStringTest {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
public void testString(){
// 存入String类型的数据(直接使用Spring提供的StringRedisTemplate就行了)
stringRedisTemplate.opsForValue().set("name","张三");
// 获取存入的数据
Object name = stringRedisTemplate.opsForValue().get("name");
System.out.println("name = " + name);
}
// ObjectMapper是SpringMVC默认的JSON处理工具
private static final ObjectMapper mapper = new ObjectMapper();
@Test
public void testObject() throws JsonProcessingException {
// 创建User对象(需要手动序列化和反序列化,其实可以通过AOP封装一个方法)
User user = new User("张三", 21);
// 手动序列化
String json = mapper.writeValueAsString(user);
// 将数据存入Redis中
stringRedisTemplate.opsForValue().set("user",json);
// 获取存入的数据
String name = stringRedisTemplate.opsForValue().get("user");
// 手动反序列化
User user1 = mapper.readValue(json, User.class);
System.out.println("user1 = " + user1);
}
}
分布式锁-Redission
Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务,其中就包含了各种分布式锁的实现。
引入依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.13.6</version>
</dependency>
配置Redisson客户端:
@Configuration
public class RedissonConfig {
@Bean
public RedissonClient redissonClient(){
// 配置
Config config = new Config();
config.useSingleServer().setAddress("redis://192.168.150.101:6379")
.setPassword("123321");
// 创建RedissonClient对象
return Redisson.create(config);
}
}
使用
@Resource
private RedissionClient redissonClient;
void testRedisson() throws Exception{
//获取锁(可重入),指定锁的名称
RLock lock = redissonClient.getLock("anyLock");
//尝试获取锁,参数分别是:获取锁的最大等待时间(期间会重试),锁自动释放时间,时间单位
boolean isLock = lock.tryLock(1,10,TimeUnit.SECONDS);
//判断获取锁成功
if(isLock){
try{
System.out.println("执行业务");
}finally{
//释放锁
lock.unlock();
}
}
}