Redis序列化

什么是序列化

  • JSON 序列化的结果是一个字符串、便于人类阅读和理解
  • Protobuf 序列化的结果是紧凑的二进制格式,体积更小、性能更高,但不易于人类阅读

 

为什么要序列化

  • 使用RedisTemplate模板就一定需要序列化,只是选择哪种序列化的问题
  • 方便阅读
  • 节省存储空间,提高传输效率

如果没有自定义序列化方式

没有自定义序列化方式,不等于不使用序列化方式,而是会使用RedisTemplate模板自带的JdkSerializationRedisSerializer序列化方式:十六进制字符串,极大不便于阅读

        redisUtil.setCacheObject("redis", "001");
        return redisUtil.getCacheObject("redis");

自定义序列化方式

import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;



@Configuration
public class RedisConfig extends CachingConfigurerSupport {

    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);

        // key的序列化采用StringRedisSerializer
        // 虽然redis的key的类型只支持字符串,但如果此处不进行字符串序列化,则会执行默认的jdk序列化:十六进制表示
        StringRedisSerializer serializer = new StringRedisSerializer();
        template.setKeySerializer(serializer);
        template.setHashKeySerializer(serializer);

        // value值的序列化采用fastJsonRedisSerializer (具体情况具体分析)
        FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
        template.setValueSerializer(fastJsonRedisSerializer);
        template.setHashValueSerializer(fastJsonRedisSerializer);

        return template;
    }
}

记录一次反序列遇到的问题

问题描述

模拟生成环境的redis序列化方式,相关RedisConfig配置、自定义序列化及反序列化类、Redis工具类等都是直接Copy的,可就是无法将redis中的对象反序列化出来。

TDevicePropertyReport tDevicePropertyReport = redisUtil.getCacheObject(key);

可生成环境却正常运行!!!

 

一直想的是会不会有什么配置漏了,直到发现Redis中的存储内容,一切都明白了

问题的本质

Redis序列化的时候是会将对象的类型一起进行存储的,并且是完整记录了该对象的存储路径

所以存的时候对象路径和取的时候对象路径一定要一致。(我的问题就是对象路径不一致)

 

解决方案

方案一

更改对象路径配置:该方式可以存也可以取

方案二

该方式只能取,不能存;因为路径不一致,存新对象的话会导致原本系统无法反序列化

public void contextLoads() {
        Collection<String> keys = redisUtil.keys("device_report:".concat("*"));
        for (String key : keys) {
            JSONObject cacheObject = redisUtil.getCacheObject(key);
            TDevicePropertyReport tDevicePropertyReport = JSON.parseObject(cacheObject.toJSONString(), TDevicePropertyReport.class);
            System.out.println(tDevicePropertyReport.getCarNum());
        }
    }

 

参考链接

【1】SpringBoot集成Redis demo

【2】Redis反序列化问题

【3】Redis序列化问题

posted @ 2023-12-04 14:45  先娶国王后取经  阅读(2)  评论(0编辑  收藏  举报