Redis 序列化值,多了雙引號問題
問題
有兩個服務:A 服務和 B 服務,A 服務負責將數據寫入 Redis 的 Hash 中,B 服務負責從 Redis 中讀取這些數據。在實際運行中,B 服務讀取到的數字類型字符串與 A 服務寫入的值不一致:
圖片
問題排查,最終發現通過hgetall命令返回字符串多加了有引號:
圖片
這里懷疑可能是Redis配置中的序列化參數設置導致的
序列化與反序列化
Redis序列化和反序列化是將數據結構轉換為二進制格式和將二進制數據轉換為對應的數據結構的過程。
序列化的作用是將數據結構轉換為二進制形式,以便于傳輸和存儲。它可以將數據保存在文件、數據庫或者網絡上,并能夠被其他程序使用。序列化還能夠對數據進行壓縮,并提供靈活的數據交換格式。
反序列化則是將二進制數據轉化為對應的數據結構,方便在Redis內部進行存儲和查詢等操作。這樣可以實現對數據的讀取和寫入。
Redis支持多種數據結構的序列化和反序列化,包括string、hash、list、set、zset。
SpringBoot提供了多種Redis序列化方式,包括JDK序列化、JSON序列化、FastJSON序列化、Jackson序列化、Protobuf序列化等。其中JDK序列化是默認的序列化方式。
常見的序列化器
- StringRedisSerializer:用于字符串的序列化和反序列化。適用于簡單的字符串鍵值對。
- Jackson2JsonRedisSerializer:使用 Jackson 庫進行 JSON 序列化和反序列化。適用于復雜對象的序列化。
- GenericJackson2JsonRedisSerializer:類似于 Jackson2JsonRedisSerializer,但可以處理泛型對象。
- OxmMarshaler:使用 Spring 的 Object-XML 映射功能進行序列化和反序列化。適用于 XML 數據。
- GenericToStringSerializer:將對象轉換為字符串,適用于簡單的對象。
A服務
使用了Jackson2JsonRedisSerializer
private RedisTemplate<String, Object> createRedisTemplate(JedisConnectionFactory connectionFactory) {
// 序列化配置
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance , ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(connectionFactory);
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setDefaultSerializer(jackson2JsonRedisSerializer);
redisTemplate.setEnableDefaultSerializer(true);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
B服務
此服務為c++端,使用默認String,該端不做調整的話,修復A端為new StringRedisSerializer()方式
測試
圖片
使用StringRedisSerializer來序列化key和value,這個序列化器會把Java字符串直接轉換為Redis存儲的字節序列,而不添加任何額外的格式化或引號。
使用Jackson2JsonRedisSerializer來序列化key和value,會把Java對象序列化為JSON格式的字符串。如果你序列化的是Java字符串,那么它就會被JSON格式化,并在最終存儲在Redis中時帶有雙引號。