Redis序列化器

引言

SpringDataRedis的使用步骤:

  • 引入spring-boot-starter-data-redis依赖

  • 在application.yml配置Redis信息

  • 注入RedisTemplate

在使用SpringDataRedis时,必然需要注入RedisTemplate,并进行对Redis的相关操作。

SpringDataRedis的序列化方式

RedisTemplate可以接收任意Object作为值写入Redis,只不过写入前会把Object序列化为字节形式,默认是采用JDK序列化。绝大多数情况下,不推荐使用 JdkSerializationRedisSerializer 进行序列化。主要是不方便人工排查数据,且操作的对象还需要实现Serializable 接口。

问题:

序列化方式一

使用配置类自定义序列化方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* Redis配置类
*/

@Configuration
public class RedisConfig extends CachingConfigurerSupport {

@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {

RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();

// 默认的Key序列化器为:JdkSerializationRedisSerializer
// 设置键的序列化器
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());

// 设置值的序列化器
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer()); 手动序列化

redisTemplate.setConnectionFactory(connectionFactory);

return redisTemplate;
}

}

尽管JSON的序列化方式可以满足我们的需求,但依然存在一些问题:为了在反序列化时知道对象的类型,JSON序列化器会将类的Class类型写入json结果中,存入Redis,会带来额外的内存开销。

内存开销问题:

序列化方式二

为了节省内存空间,我们并不会使用JSON序列化器来处理value,而是统一使用String序列化器,要求只能存储String类型的key和value。当需要存储Java对象时,手动完成对象的序列化和反序列化。

注入StringRedisTemplate对象,该对象key和value默认使用的是String序列化器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Autowired
private StringRedisTemplate stringRedisTemplate;
// JSON工具
private static final ObjectMapper mapper = new ObjectMapper();

@Test
void testStringTemplate() throws JsonProcessingException {
// 准备对象
User user = new User("虎哥", 18);
// 手动序列化
String json = mapper.writeValueAsString(user);
// 写入一条数据到redis
stringRedisTemplate.opsForValue().set("user:200", json);
// 读取数据
String val = stringRedisTemplate.opsForValue().get("user:200");
// 反序列化
User user1 = mapper.readValue(val, User.class);
System.out.println("user1 = " + user1);
}

Tips:该方式解决了Redis存储额外开销的问题,但需要使用json工具对需要缓存的对象进行序列化后再存储,取值的时候需要反序列化成对应的对象。