精华内容
下载资源
问答
  • 2022-05-11 09:44:39

    Redis序列化方式

    1. JdkSerializationRedisSerializer

    这是RestTemplate类默认的序列化方式。

    优点:

    反序列化时不需要提供类型信息(class),
    缺点:

    需要实现Serializable接口
    存储的为二进制数据
    序列化后的结果非常庞大,是JSON格式的5倍左右,这样就会消耗redis服务器的大量内存

    2. StringRedisSerializer

    是StringRedisTemplate默认的序列化方式,key和value都会采用此方式进行序列化,是被推荐使用的,对开发者友好,轻量级,效率也比较高。

    3. GenericToStringSerializer

    需要调用者给传一个对象到字符串互转的Converter

    4. Jackson2JsonRedisSerializer

    优点:

    速度快,序列化后的字符串短小精悍,不需要实现Serializable接口。
    缺点:

    此类的构造函数中有一个类型参数,必须提供要序列化对象的类型信息(.class对象),其在反序列化过程中用到了类型信息

    5. GenericJackson2JsonRedisSerializer

    与Jackson2JsonRedisSerializer大致相同,会额外存储序列化对象的包命和类名

    更多相关内容
  • redis序列化方式

    千次阅读 2019-04-25 14:38:00
    redis序列化方式 (内容复制别人的博客,留作学习笔记) spring-data-redis的序列化类有下面这几个: GenericToStringSerializer: 可以将任何对象泛化为字符串并序列化 Jackson2JsonRedisSerializer: 跟...

    redis序列化方式 (内容复制别人的博客,留作学习笔记)

    spring-data-redis的序列化类有下面这几个:
    GenericToStringSerializer: 可以将任何对象泛化为字符串并序列化
    Jackson2JsonRedisSerializer: 跟JacksonJsonRedisSerializer实际上是一样的
    JacksonJsonRedisSerializer: 序列化object对象为json字符串
    JdkSerializationRedisSerializer: 序列化java对象(被序列化的对象必须实现Serializable接口)
    StringRedisSerializer: 简单的字符串序列化
    GenericToStringSerializer:类似StringRedisSerializer的字符串序列化
    GenericJackson2JsonRedisSerializer:类似Jackson2JsonRedisSerializer,但使用时构造函数不用特定的类
    参考以上序列化,自定义序列化类

    Jdk序列化速度快,占用空间大,不易查看,通过redis命令查看类似\xAC\xED\x00\x05t\x00\x011不方便
    Hash最好还是用GenericJackson2JsonRedisSerializer

    在用spring-data-redis做redis缓存的时候,指定RedisTemplate的key和value序列化时遇到的问题。

    RedisTemplate的key指定成StringRedisSerializer序列化会报类型转换错误,如XXX类不能转换成String。
    使用Jackson2JsonRedisSerializer序列化的时候,如果实体类上没有set方法反序列化会报错。

    同时采用了StringRedisTemplate和RedisTemplate时注意
    并且对存储String与存储Java对象采用不同的Template进行了简单的封装。

    spring-data-redis默认采用的序列化策略有两种,一种是String的序列化策略,一种是JDK的序列化策略。

    StringRedisTemplate默认采用的是String的序列化策略,保存的key和value都是采用此策略序列化保存的。StringRedisSerializer

    RedisTemplate默认采用的是JDK的序列化策略,保存的key和value都是采用此策略序列化保存的。JdkSerializationRedisSerializer

    推荐将所有Template的key都采用String的序列化方式,而value的序列化方式可以采用不同的序列化方式。(jreids自动选择)(这样还有一个好处就是不必string的也采用jdk的序列化从而导常用数据格式致为了存储数据结构浪费空间)

    参考https://blog.csdn.net/y666666y/article/details/70212767

    @Configuration
    public class RedisConfiguration {
    
        @SuppressWarnings("unchecked")
        @Bean(name = "objectRedisTemplate")
        public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
            RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
            redisTemplate.setConnectionFactory(redisConnectionFactory);
    
            @SuppressWarnings("")
            Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
    
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
            objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
            jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
    
            redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
            redisTemplate.setKeySerializer(new StringRedisSerializer());
    
            redisTemplate.afterPropertiesSet();
    
            return redisTemplate;
        }
    }
    
    展开全文
  • 当我们的数据存储到Redis的时候,我们的键(key)和值(value)都是通过Spring提供的Serializer序列化到数据库的。RedisTemplate默认使用的是JdkSerializationRedisSerializer,StringRedisTemplate默认使用的是...

    当我们的数据存储到Redis的时候,我们的键(key)和值(value)都是通过Spring提供的Serializer序列化到数据库的。RedisTemplate默认使用的是JdkSerializationRedisSerializer,StringRedisTemplate默认使用的是StringRedisSerializer。

    Spring Data JPA为我们提供了下面的Serializer:GenericToStringSerializer、Jackson2JsonRedisSerializer、JacksonJsonRedisSerializer、JdkSerializationRedisSerializer、OxmSerializer、StringRedisSerializer。

    序列化方式对比:

    • JdkSerializationRedisSerializer: 使用JDK提供的序列化功能。 优点是反序列化时不需要提供类型信息(class),但缺点是需要实现Serializable接口,还有序列化后的结果非常庞大,是JSON格式的5倍左右,这样就会消耗redis服务器的大量内存。
    • Jackson2JsonRedisSerializer: 使用Jackson库将对象序列化为JSON字符串。优点是速度快,序列化后的字符串短小精悍,不需要实现Serializable接口。但缺点也非常致命,那就是此类的构造函数中有一个类型参数,必须提供要序列化对象的类型信息(.class对象)。 通过查看源代码,发现其只在反序列化过程中用到了类型信息。

    问题描述

    我们在用Spring data redis做redis缓存的时候,指定RedisTemplate的key和value序列化时遇到的问题。

    1. RedisTemplate的key指定成StringRedisSerializer序列化会报类型转换错误,如XXX类不能转换成String。
    2. 使用Jackson2JsonRedisSerializer序列化的时候,如果实体类上没有set方法反序列化会报错。

    问题分析

    问题1:使用StringRedisSerializer做key的序列化时,StringRedisSerializer的泛型指定的是String,传其他对象就会报类型转换错误,在使用@Cacheable注解是key属性就只能传String进来。把这个序列化方式重写了,将泛型改成Object。源码:

    
    /**
     * 必须重写序列化器,否则@Cacheable注解的key会报类型转换错误
     *
     * @authors yuhao.wang
     */
    public class StringRedisSerializer implements RedisSerializer<Object> {
    
        private final Charset charset;
    
        private final String target = "\"";
    
        private final String replacement = "";
    
        public StringRedisSerializer() {
            this(Charset.forName("UTF8"));
        }
    
        public StringRedisSerializer(Charset charset) {
            Assert.notNull(charset, "Charset must not be null!");
            this.charset = charset;
        }
    
        @Override
        public String deserialize(byte[] bytes) {
            return (bytes == null ? null : new String(bytes, charset));
        }
    
        @Override
        public byte[] serialize(Object object) {
            String string = JSON.toJSONString(object);
            if (string == null) {
                return null;
            }
            string = string.replace(target, replacement);
            return string.getBytes(charset);
        }
    }
    

    问题2:我们放弃用jackjson来做value的序列化,使用FastJson来做。重写一些序列化器,并实现RedisSerializer接口。源码如下:

    
    public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
    
        public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
    
        private Class<T> clazz;
    
        public FastJsonRedisSerializer(Class<T> clazz) {
            super();
            this.clazz = clazz;
        }
    
        @Override
        public byte[] serialize(T t) throws SerializationException {
            if (t == null) {
                return new byte[0];
            }
            return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
        }
    
        @Override
        public T deserialize(byte[] bytes) throws SerializationException {
            if (bytes == null || bytes.length <= 0) {
                return null;
            }
            String str = new String(bytes, DEFAULT_CHARSET);
            return (T) JSON.parseObject(str, clazz);
        }
    
    }
    

    新加入一种序列化KryoRedisSerializer。速度很快,源码如下:

    
    
    import com.esotericsoftware.kryo.Kryo;
    import com.esotericsoftware.kryo.io.Input;
    import com.esotericsoftware.kryo.io.Output;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.data.redis.serializer.RedisSerializer;
    import org.springframework.data.redis.serializer.SerializationException;
    
    import java.io.ByteArrayOutputStream;
    
    /**
     * @param <T>
     * @author yuhao.wang
     */
    public class KryoRedisSerializer<T> implements RedisSerializer<T> {
        Logger logger = LoggerFactory.getLogger(KryoRedisSerializer.class);
    
        public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
    
        private static final ThreadLocal<Kryo> kryos = ThreadLocal.withInitial(Kryo::new);
    
        private Class<T> clazz;
    
        public KryoRedisSerializer(Class<T> clazz) {
            super();
            this.clazz = clazz;
        }
    
        @Override
        public byte[] serialize(T t) throws SerializationException {
            if (t == null) {
                return EMPTY_BYTE_ARRAY;
            }
    
            Kryo kryo = kryos.get();
            kryo.setReferences(false);
            kryo.register(clazz);
    
            try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
                 Output output = new Output(baos)) {
                kryo.writeClassAndObject(output, t);
                output.flush();
                return baos.toByteArray();
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
    
            return EMPTY_BYTE_ARRAY;
        }
    
        @Override
        public T deserialize(byte[] bytes) throws SerializationException {
            if (bytes == null || bytes.length <= 0) {
                return null;
            }
    
            Kryo kryo = kryos.get();
            kryo.setReferences(false);
            kryo.register(clazz);
    
            try (Input input = new Input(bytes)) {
                return (T) kryo.readClassAndObject(input);
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
    
            return null;
        }
    
    }
    

    自定义序列化的使用

    
    /**
     * @author yuhao.wang
     */
    @Configuration
    public class RedisConfig {
    
        /**
         * 重写Redis序列化方式,使用Json方式:
         * 当我们的数据存储到Redis的时候,我们的键(key)和值(value)都是通过Spring提供的Serializer序列化到数据库的。RedisTemplate默认使用的是JdkSerializationRedisSerializer,StringRedisTemplate默认使用的是StringRedisSerializer。
         * Spring Data JPA为我们提供了下面的Serializer:
         * GenericToStringSerializer、Jackson2JsonRedisSerializer、JacksonJsonRedisSerializer、JdkSerializationRedisSerializer、OxmSerializer、StringRedisSerializer。
         * 在此我们将自己配置RedisTemplate并定义Serializer。
         *
         * @param redisConnectionFactory
         * @return
         */
        @Bean
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
            RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
            redisTemplate.setConnectionFactory(redisConnectionFactory);
            
            FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);
            // 全局开启AutoType,不建议使用
            // ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
            // 建议使用这种方式,小范围指定白名单
            ParserConfig.getGlobalInstance().addAccept("com.xiaolyuh.");
    
            // 设置值(value)的序列化采用FastJsonRedisSerializer。
            redisTemplate.setValueSerializer(fastJsonRedisSerializer);
            redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
            // 设置键(key)的序列化采用StringRedisSerializer。
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            redisTemplate.setHashKeySerializer(new StringRedisSerializer());
    
            redisTemplate.afterPropertiesSet();
            return redisTemplate;
        }
    
    }
    

    注意:fastjson在2017年3月爆出了在1.2.24以及之前版本存在远程代码执行高危安全漏洞。所以要使用ParserConfig.getGlobalInstance().addAccept("com.xiaolyuh.");指定序列化白名单。详情可以点击这里查看

    参考:

    展开全文
  • Redis序列化方式比较

    千次阅读 2019-03-09 23:20:35
    1.Spring-Data-Redis支持的序列化策略 SpringBoot默认提高StringRedisTemplate和RedisTemplate,前者用于操作包含字符串的数据机构,后者则使用了JDK自带的序列化策略。 事实上StringRedisTemplate继承了...

    1.Spring-Data-Redis支持的序列化策略

    SpringBoot默认提高StringRedisTemplate和RedisTemplate,前者用于操作包含字符串的数据机构,后者则使用了JDK自带的序列化策略。

    事实上StringRedisTemplate继承了RedisTemplate,对key、value 、hashkey、hashvalue提供了不同的序列化策略:

    public class StringRedisTemplate extends RedisTemplate<String, String> {
        public StringRedisTemplate() {
            this.setKeySerializer(RedisSerializer.string());
            this.setValueSerializer(RedisSerializer.string());
            this.setHashKeySerializer(RedisSerializer.string());
            this.setHashValueSerializer(RedisSerializer.string());
        }
    }
    

    key                                普通key,非hash
    value                             普通value,非hash
    hashKey                        hash的filed
    hashValue                     hash的value

    RedisTemplate采用的默认的序列化策略JdkSerializationRedisSerializer。这种序列化策略实现了RedisSerializer接口,定义如下:

    public interface RedisSerializer<T> {
        @Nullable
        byte[] serialize(@Nullable T var1) throws SerializationException;
    
        @Nullable
        T deserialize(@Nullable byte[] var1) throws SerializationException;
    
    }
    

    serialize方法:将默认的对象转换成字节数组,以提供给RedisCollection操作。
    deserialize方法:将RedisCollection读取带的byte[]数组转换为对象。

    StringRedisTemplate则使用了StringRedisSerializer来将字符串转换为字节数组,将读取到的字节数组转换为字符串。

    2.Spring-Data-Redis的序列化类有下面这几个:

    GenericToStringSerializer: 可以将任何对象泛化为字符串并序列化
    Jackson2JsonRedisSerializer: 跟JacksonJsonRedisSerializer实际上是一样的
    JacksonJsonRedisSerializer: 序列化object对象为json字符串
    JdkSerializationRedisSerializer: 序列化java对象(被序列化的对象必须实现Serializable接口),无法转义成对象
    StringRedisSerializer: 简单的字符串序列化
    GenericToStringSerializer:类似StringRedisSerializer的字符串序列化
    GenericJackson2JsonRedisSerializer:类似Jackson2JsonRedisSerializer,但使用时构造函数不用特定的类参考以上序列化,自定义序列化类; 

    key和hashKey:推荐使用 StringRedisSerializer: 简单的字符串序列化

    value和hashValue:推荐使用GenericJackson2JsonRedisSerializer:类似Jackson2JsonRedisSerializer,但使用时构造函数不用特定的类

     

    3.自定义序列化实例

    配置自定义序列化策略:

    @Configuration
    public class RedisConfig {
        private static Logger logger = LoggerFactory.getLogger(RedisConfig.class);
    
        @Bean(name = "springSessionDefaultRedisSerializer")
        public GenericJackson2JsonRedisSerializer getGenericJackson2JsonRedisSerializer() {
            return new GenericJackson2JsonRedisSerializer();
        }
        @Bean
        public RedisTemplate<String, Object> getRedisTemplate(
                JedisConnectionFactory connectionFactory) {
            RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
            redisTemplate.setConnectionFactory(connectionFactory);
            redisTemplate.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());
            StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
            redisTemplate.setKeySerializer(stringRedisSerializer);
            redisTemplate.setHashKeySerializer(stringRedisSerializer);
            return redisTemplate;
        }
    }
    
    展开全文
  • jfinal 越来越流行, jfinal的redis插件默认的序列化方式是fst。 但是系统中其他项目中用的是spring data redis中的StringRedisTemplate,所有的value都是通过gson转化成String放进去的。 直接用jfinal的redis插件去...
  • spring-data-redis序列化方式比较

    千次阅读 2018-09-13 17:59:06
    1. spring-data-redis支持的序列化策略 spring-data-redis默认采用的序列化策略有两种,一种是String的序列化策略,一种是JDK的序列化策略。...redisTemplate可自定义各种key和各种value的序列化方式:...
  • 由于Springboot默认提供了序列化方式并不是非常理想,对于高要求的情况下,序列化的速度和序列化之后大小有要求的情况下,不能满足,所以可能需要更换序列化的方式。 这里主要记录更换序列化的方式以及其中一些出现...
  • 重写Redis序列化方式,redis可视化工具不乱码
  • 当我们的数据存储到Redis的时候,我们的键(key)和值(value)都是通过Spring提供的Serializer序列化到数据库的。RedisTemplate默认使用的是JdkSerializationRedisSerializer,StringRedisTemplate默认使用的是...
  • Redis序列化的几种方式

    千次阅读 多人点赞 2019-12-12 15:03:36
    Redis序列化的几种方式 1.什么是Redis Redis是用C语言开发的一个开源的高性能键值对(key-value)数据库。它通过提供多种键值数据类型来适应不同场景下的存储需求,目前为止Redis支持的键值数据类型如下: 1、 字符...
  • 今天进行redis配置没有注意redis设置序列化方式的方法名称,导致redis序列化一直不成功。 @Configuration public class RedisConfig { @Bean public RedisTemplate<Object, Object> redisTemplate...
  • SpringBoot整合Redis序列化
  • 主要介绍了SpringBoot Redis配置Fastjson进行序列化和反序列化实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • Redis序列化对象的几种方式

    千次阅读 2020-11-19 16:06:45
    redis的value使用以下序列化方式进行序列化操作: 1:JdkSerializationRedisSerializer: 2:GenericJackson2JsonRedisSerializer 3:StringRedisSerializer 4:GenericFastJsonRedisSerializer 发现只有4:...
  • Redis序列化对象的几种方式比较

    千次阅读 2019-04-29 20:40:32
    redis的value使用以下序列化方式进行序列化操作: 1:JdkSerializationRedisSerializer: 2:GenericJackson2JsonRedisSerializer 3:StringRedisSerializer 4:GenericFastJsonRedisSerializer 发现只有4:...
  • 常见的的序列化反序列方式的效率:protoBuf(PB) > fastjson > jackson > hessian > xstream > java数据来自于:https://github.com/eishay/jvm-serializers/wiki所以我选择了java方式、jackson方式、...
  • Redis几种序列化方式分析

    千次阅读 2019-12-15 20:29:19
    一般redis序列化方式主要有:字符串序列化、json序列化、xml序列化、jdk序列化,具体可查阅org.springframework.data.redis.serializer.RedisSerializer 的实现类,其中对于json序列化,官方实现的是jackson的序列...
  • springboot集成redis序列化问题汇总

    千次阅读 2022-04-03 22:54:09
    两种方案中都需要对序列化方式进行设置,否则会出现二进制格式的数据(不论是Redis desktop manager工具还是redis自带客户端黑窗口打开),如果需要查看数据则会影响观感,关于序列化方式设置底层都是对RedisSerializer...
  • Redis实现自定义序列化方式

    千次阅读 2020-07-30 11:06:45
    1. 如何实现redis序列化序列化:把对象转换为字节序列的过程称为对象的序列化。 反序列化:把字节序列恢复为对象的过程称为对象的反序列化序列化主要用于存储对象状态为另一种通用格式,比如存储为二进制、...
  • redis 序列化对象问题

    2022-01-17 11:54:10
    redis 序列化背景追根溯源RedisTemplateRedisSerializerJdkSerializationRedisSerializer总结 背景 最近在使用redis的发布订阅模式时,订阅类接收到的是字符串,习惯性的用JSON将字符串转成对象,结果就是各种报错,...
  • 主要介绍了SpringBoot2.3整合redis缓存自定义序列化的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • Redis 序列化

    2021-12-03 14:25:53
    我们在用redis存储数据的时候,若果默认使用JDK的序列化方式,在Redis桌面花的工具中查看就会使乱码的情况,所以我们需要自定义redis序列化方式,使用jackson2JsonRedisSerializer,复制下面这段即可 @...
  • 今天遇到了一个问题,发现使用springdata redis添加缓存,key中多了一个前缀,\xac\xed\x00\x05t\x00\x1a,后来发现是因为序列化没有配置,配置代码如下 @Configuration public class RedisConfig { @Bean public...
  • redis不同序列化方式性能对比

    千次阅读 2019-12-15 20:43:14
    Redis的value序列化方式一般有两种:JSON方式和JDK方式 有以下几个序列化工具类: 第一次使用的是JDK方式进行测试 使用jdk方式需要pojo类实现Serializable接口 public void addByJDK() { //随机生五万条消息的一个...
  • redis的hash数据类型,序列化方式默认使用的是对象序列化,会显示乱码 redisTemplate.setKeySerializer(new StringRedisSerializer()); //hash内部对象序列化,解决对象乱码 redisTemplate.setHashKeySerializer(new...
  • 企业级项目中Redis序列化配置方案
  • redis 序列化 报错

    2021-09-13 15:15:54
    nested exception is java.lang.ClassNotFoundException 1 对象序列化存入redis后,包名被修改,导致取出对象反序列化时包名不一致,报错 解决方案:清空redis 2 序列化与反序列化方式不对称也可能导致报错 解决...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 100,905
精华内容 40,362
关键字:

redis序列化方式