跳到主要内容

奇怪的bug记录

spring redis 业务代码配置不同序列化

redis template get string类型, 结果还是报错string类型不符合序列化要求, 非常神奇.

redis里检查数据, 发现报错的文本有额外的双引号, 而没报错的则是纯粹的文本. 前者是升级前的存量缓存, 后者是新的缓存.

排查一番发现, 就算是字符串, 也会出现序列化不同导致无法解析的情况.

  • 业务代码历史版本的redis template没有配置序列化信息, 使用的是jdk里的默认序列化.
  • 新的代码redis template配置了序列化参数, 使用的是jackson json的序列化.

https://docs.spring.io/spring-data/data-keyvalue/docs/current/api/org/springframework/data/keyvalue/redis/core/RedisTemplate.html

Performs automatic serialization/deserialization between the given objects and the underlying binary data in the Redis store. By default, it uses Java serialization for its objects (through JdkSerializationRedisSerializer). For String intensive operations consider the dedicated StringRedisTemplate.

Note that while the template is generified, it is up to the serializers/deserializers to properly convert the given Objects to and from binary data.

redisTemplate可以不配置直接使用, 也可以额外配置序列化mapper, 不想考虑这些可以直接使用StringRedisTemplate.

import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();

template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(
Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
jackson2JsonRedisSerializer.setObjectMapper(om);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}