快速入门
redis客户端选择
jedis使用简单,但是线程不安全,在多线程环境下需要基于连接池使用,lettuce基于netty实现,支持同步,异步,响应式编程,而Spring Date Redis定义了一套API兼容了上面两种
Spring Date Redis集成了不同的java客户端,提供RedisTemplate统一API操作redis,支持基于json,String,JDK,对象进行序列化和反序列化
Redis的基础使用
使用Spring Date Redis的步骤
引入依赖
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.12.0</version> </dependency> </dependencies>
填写配置文件
spring: data: redis: host: 192.168.200.128 port: 6379 password: lettuce: pool: max-active: 8 # 最大连接连接数 max-idle: 8 # 最大空闲连接数 min-idle: 0 # 最小空闲连接数 max-wait: 2000ms # 等待时间,默认是-1,永久等待
pool有默认值,可以配置
测试
@SpringBootTest class ReidsDemoApplicationTests { @Autowired private RedisTemplate redisTemplate; @Test void contextLoads() { // 设置 redisTemplate.opsForValue().set("name","zhangsan"); // 查询 System.out.println(redisTemplate.opsForValue().get("name")); } }
redis的序列化
在Spring Date Redis的RedisTemplate,能够将任何类型的对象转换成redis能够接收的字节,但是一般默认采用的序列化方式是JDK的序列化方式,这种序列化的缺点是占用空间大,难看懂,一般使用redis需要自己指定序列化方式,key一般是String类型的,value一般是Object类型的,所以key使用的序列化器是StringRedisSerializer,value使用的序列化器是GenericJackson2JsonRedisSerializer。
在redis中有key和hash key,他们是什么,有什么区别?
在redis数据结构中,使用key和value来存储数据,这个key是用来在数据库中唯一标识一个数据的标识符,redis有很多的数据结构,有一种是hash,在这种数据结构中,不仅需要使用key来唯一标识一个hash数据,在内部的每一个键值对中也需要一个唯一标识符,这个标识符就是hash key。在hash中,它的键值对还有一个value,这个value叫做hash value
@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;
}
}
将对象作为value存储到redis会出现什么问题
@SpringBootTest
class ReidsDemoApplicationTests {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Test
void contextLoads() {
// 设置
User user = new User("李四",10);
redisTemplate.opsForValue().set("user:110",user);
// 查询
System.out.println(redisTemplate.opsForValue().get("user:110"));
}
}
存入进去会多保存一个class字节码,这个是为了能够自动的反序列化,但是但数据量大的情况下会占用大量内存,所以一般不使用json序列化器转换value,key和value都是使用String的形式存储,减少的内存的占用,但是序列化和反序列化需要手动指定。
StringRedisTemplate默认的key value的序列化方式都是String
StringRedisTemplate
@Autowired
private StringRedisTemplate stringRedisTemplate;
// JSON序列化工具
private static final ObjectMapper mapper = new ObjectMapper();
@Test
void testSaveUser() throws JsonProcessingException {
// 创建对象
User user = new User("虎哥", 21);
// 手动序列化
String json = mapper.writeValueAsString(user);
// 写入数据
stringRedisTemplate.opsForValue().set("user:200", json);
// 获取数据
String jsonUser = stringRedisTemplate.opsForValue().get("user:200");
// 手动反序列化
User user1 = mapper.readValue(jsonUser, User.class);
System.out.println("user1 = " + user1);
}