欢迎来到 请回答1024 的博客 |
🍓🍓🍓欢迎来到 请回答1024的博客
关于博主: 我是 请回答1024,一个追求数学与计算的边界、时间与空间的平衡,0与1的延伸的后端开发者。
博客特色: 在我的博客中,开设了如下专栏(点击可以进入专栏奥~): Java、MySQL、Redis、Spring、SpringBoot、SpringCloud、RabbitMQ、微服务、分布式 等相关技术专栏。期待与您一起,探索编程世界中的发现和创新之旅。
🍎🍎🍎我的主页 : https://reply1024.blog.csdn.net
敬请期待定期更新、见解和教程!让我们一起踏上这段编码冒险之旅!
数学与计算的边界 时间与空间的平衡 0与1的延伸 |
# ⛄概述 `SpringData`是`Spring`中数据操作的模块,包含对各种数据库的集成,其中对`Redis`的集成模块就叫做`SpringDataRedis`,官网地址:[https://spring.io/projects/spring-data-redis](https://spring.io/projects/spring-data-redis)
- 提供了对不同Redis客户端的整合(Lettuce和Jedis)
- 提供了RedisTemplate统一API来操作Redis
- 支持Redis的发布订阅模型
- 支持Redis哨兵和Redis集群
- 支持基于Lettuce的响应式编程
- 支持基于JDK.JSON.字符串.Spring对象的数据序列化及反序列化
- 支持基于Redis的JDKCollection实现
SpringDataRedis
中提供了RedisTemplate
工具类,其中封装了各种对Redis
的操作。并且将不同数据类型的操作API封装到了不同的类型中:
⛄快速入门
SpringBoot
已经提供了对SpringDataRedis
的支持,使用非常简单:
❄️❄️导入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.7</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<name>redis-demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--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>
<!--Jackson依赖-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</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>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
❄️❄️配置文件
spring:
redis:
host: ip
port: 6379
password: 密码
lettuce:
pool:
max-active: 8 #最大连接
max-idle: 8 #最大空闲连接
min-idle: 0 #最小空闲连接
max-wait: 100ms #连接等待时间
❄️❄️测试代码
@SpringBootTest
class RedisDemoApplicationTests {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Test
void testString() {
// 写入一条String数据
redisTemplate.opsForValue().set("name", "mayun");
// 获取string数据
Object name = redisTemplate.opsForValue().get("name");
System.out.println("name = " + name);
}
}
⛄数据化序列器
RedisTemplate
可以接收任意Object
作为值写入Redis:
只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化,得到的结果是这样的:
缺点:
- 可读性差
- 内存占用较大
可以自定义如下配置:
@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;
}
}
这里采用了JSON序列化来代替默认的JDK序列化方式。最终结果如图:
图略。
整体可读性有了很大提升,并且能将Java对象自动的序列化为JSON字符串,并且查询时能自动把JSON反序列化为Java对象。
不过,其中记录了序列化时对应的 class 名称,目的是为了查询时实现自动反序列化。这会带来额外的内存开销。
⛄StringRedisTemplate
尽管之前 JSON 的序列化方式可以满足我们的需求,但依然存在一些问题,如下:
{
"Class": "com.snow.Student",
"name": "wang",
"age": 18
}
为了在反序列化时知道对象的类型,JSON序列化器会将类的 class 类型写入json结果中,存入Redis,会带来额外的内存开销。
为了减少内存的消耗,我们可以采用手动序列化的方式,换句话说,就是不借助默认的序列化器,而是我们自己来控制序列化的动作,同时,我们只采用String的序列化器,这样,在存储value时,我们就不需要在内存中就不用多存储数据,从而节约我们的内存空间
这种用法比较普遍,因此SpringDataRedis就提供了RedisTemplate的子类:StringRedisTemplate
,它的key和value的序列化方式默认就是String方式。省去了我们自定义RedisTemplate的序列化方式的步骤,而是直接使用:
@SpringBootTest
class RedisStringTests {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
void testString() {
// 写入一条String数据
stringRedisTemplate.opsForValue().set("verify:phone:13600008888", "124143");
// 获取string数据
Object name = stringRedisTemplate.opsForValue().get("name");
System.out.println("name = " + name);
}
private static final ObjectMapper mapper = new ObjectMapper();
@Test
void testSaveUser() throws JsonProcessingException {
// 创建对象
User user = new User("mayun", 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);
}
}
此时我们再来看一看存储的数据,小伙伴们就会发现那个class数据已经不在了,节约了我们的空间~
{
"name": "wang",
"age": 18
}
⛄RedisTemplate的两种序列化实践方案总结
RedisTemplate的两种序列化实践方案:
方案一:
自定义RedisTemplate
修改RedisTemplate的序列化器为GenericJackson2JsonRedisSerializer
会占用额外的内存空间 记录字节码
方案二:
使用StringRedisTemplate
写入Redis时,手动把对象序列化为JSON
读取Redis时,手动把读取到的JSON反序列化为对象