• 三种序列化方式存取redis的方法


    常见的的序列化反序列方式的效率:

    protoBuf(PB) > fastjson > jackson > hessian > xstream > java

    数据来自于:https://github.com/eishay/jvm-serializers/wiki

    所以我选择了java方式、jackson方式、fastjson方式、pb方式做了封装并测试,测试结果如下:

    jackson、pb、fastjson差不太多,jackson稍好些,java方式非常慢不推荐,jackson是springboot自带的json序列化工具,所以推荐这种方式做redis对象存取。

    下面是四种实现方式:

    java自带序列化

    序列化工具方法

      /**
             * 序列化
             *
             * @param object
             * @return
             */
            public static byte[] serialize(Object object) {
                ObjectOutputStream oos = null;
                ByteArrayOutputStream baos = null;
                try {
                    // 序列化
                    baos = new ByteArrayOutputStream();
                    oos = new ObjectOutputStream(baos);
                    oos.writeObject(object);
                    byte[] bytes = baos.toByteArray();
                    return bytes;
                } catch (Exception e) {
                    throw new RuntimeException(e.getMessage(), e);
                }
            }
    
            /**
             * 反序列化
             *
             * @param bytes
             * @return
             */
            public static Object unserialize(byte[] bytes) {
                ByteArrayInputStream bais = null;
                try {
                    // 反序列化
                    bais = new ByteArrayInputStream(bytes);
                    ObjectInputStream ois = new ObjectInputStream(bais);
                    return ois.readObject();
                } catch (Exception e) {
                    throw new RuntimeException(e.getMessage(), e);
                }
            }

    redisUtils

      
      
    @Autowired
      private StringRedisTemplate redisTemplate;
      /**
         * 以二进制序列化方式向redis保存对象 2019
         *
         * @param key
         * @param value
         */
        public void setObj(String key, Object value) {
            final byte[] vbytes = SerializeUtil.serialize(value);
            redisTemplate.execute(new RedisCallback() {
                @Override
                public Object doInRedis(RedisConnection connection) throws DataAccessException {
    //                connection.set(redisTemplateSer.getStringSerializer().serialize(key), vbytes);
                    connection.set(SerializeUtil.serialize(key), vbytes);
                    return null;
                }
            });
        }
    
        /**
         * 以二进制序列化方式从redis获取对象 2019
         *
         * @param key
         * @param <T>
         * @return
         */
        public <T> T getObj(String key) {
            return redisTemplate.execute(new RedisCallback<T>() {
                @Override
                public T doInRedis(RedisConnection connection) throws DataAccessException {
    //                byte[] keyByte = redisTemplateSer.getStringSerializer().serialize(key);
                    byte[] keyByte = SerializeUtil.serialize(key);
    
                    if (connection.exists(keyByte)) {
                        byte[] valuebytes = connection.get(keyByte);
                        @SuppressWarnings("unchecked")
                        T value = (T) SerializeUtil.unserialize(valuebytes);
                        return value;
                    }
                    return null;
                }
            });
        }

    Jackson、fastjson

    序列化工具方法

            /**
             * jackson序列化反序列化工具
             */
            private static ObjectMapper objectMapper = new ObjectMapper();
    
            public static <T> String obj2String(T obj) {
                if (obj == null) {
                    return null;
                }
                try {
                    return obj instanceof String ? (String) obj : objectMapper.writeValueAsString(obj);
                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
            }
    
            //字符串转对象
            public static <T> T string2Obj(String str, Class<T> clazz) {
                if (StringUtils.isEmpty(str) || clazz == null) {
                    return null;
                }
                try {
                    return clazz.equals(String.class) ? (T) str : objectMapper.readValue(str, clazz);
                } catch (IOException e) {
                    e.printStackTrace();
                    return null;
                }
            }
    
    //        /**
    //         * fastjson序列化反序列化工具
    //         */
    //        public static <T> String obj2String(T obj) {
    //            return JSON.toJSONString(obj);
    //        }
    //
    //        //字符串转对象
    //        public static <T> T string2Obj(String str, Class<T> clazz) {
    //            return JSON.parseObject(str,clazz);
    //        }

    redisUtils

      /**
         * 以JSON序列化方式向redis保存对象 推荐这种用法速度快 2019
         * @param key
         * @param value
         */
        public void setObjJson(String key,Object value){
            redisTemplate.opsForValue().set(key,SerializeUtil.obj2String(value));
        }
    
        /**
         * 以JSON序列化方式从redis获取对象 推荐这种用法速度快 2019
         * @param key
         * @param clazz
         * @param <T>
         * @return
         */
        public <T> T getObjJson(String key,Class<T> clazz){
            String strValue = redisTemplate.opsForValue().get(key);
            if(!StringUtils.isEmpty(strValue)){
                T value = SerializeUtil.string2Obj(strValue,clazz);
                return value;
            }
            return null;
        }

    ProtoBuf方式

    maven依赖

            <!-- protostuff -->
            <dependency>
                <groupId>io.protostuff</groupId>
                <artifactId>protostuff-core</artifactId>
                <version>1.4.0</version>
            </dependency>
            <dependency>
                <groupId>io.protostuff</groupId>
                <artifactId>protostuff-runtime</artifactId>
                <version>1.4.0</version>
            </dependency>            

    序列化工具方法

        /**
             * protobuf序列化工具
             */
            public static <T> byte[] serializePb(T o) {
                Schema schema = RuntimeSchema.getSchema(o.getClass());
                return ProtobufIOUtil.toByteArray(o, schema, LinkedBuffer.allocate(256));
            }
    
            public static <T> T unserializePb(byte[] bytes, Class<T> clazz) {
    
                T obj = null;
                try {
                    obj = clazz.newInstance();
                    Schema schema = RuntimeSchema.getSchema(obj.getClass());
                    ProtostuffIOUtil.mergeFrom(bytes, obj, schema);
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
    
                return obj;
            }

    redisUtils,pb方式如果是嵌套对象会有一定问题(这块回头再研究一下),并且需要序列化的成员变量需要添加@Tag(7)注解,如:

    @Data
    public class SimplePojo {
        @Tag(1)
        private String a;
        @Tag(2)
        private String b;
        @Tag(3)
        private String c;
      /**
         * 以pb序列化方式向redis保存对象 2019
         *
         * @param key
         * @param value
         */
        public void setObjPb(String key, Object value) {
            final byte[] vbytes = SerializeUtil.serializePb(value);
            redisTemplate.execute(new RedisCallback() {
                @Override
                public Object doInRedis(RedisConnection connection) throws DataAccessException {
                    connection.set(SerializeUtil.serializePb(key), vbytes);
                    return null;
                }
            });
        }
    
        /**
         * 以pb序列化方式从redis获取对象 2019
         *
         * @param key
         * @param <T>
         * @return
         */
        public <T> T getObjPb(String key,Class<T> clazz) {
            return redisTemplate.execute(new RedisCallback<T>() {
                @Override
                public T doInRedis(RedisConnection connection) throws DataAccessException {
                    byte[] keyByte = SerializeUtil.serializePb(key);
    
                    if (connection.exists(keyByte)) {
                        byte[] valuebytes = connection.get(keyByte);
                        @SuppressWarnings("unchecked")
                        T value = (T) SerializeUtil.unserializePb(valuebytes,clazz);
                        return value;
                    }
                    return null;
                }
            });
        }

    Fork From GIT

    更详细的的源码详见:https://gitee.com/zxporz/redistest/blob/master/src/main/java/org/zxp/redis/utils/RedisUtil.java

    欢迎fork

  • 相关阅读:
    Flink中的广播流之BroadcastStream
    啊。。这是为什么。。 花甜的工作笔记
    我那庞大身躯,脆弱心灵的3250 花甜的工作笔记
    好吧,我承认,我不是一个专一的人。。。 花甜的工作笔记
    沾沾自喜 花甜的工作笔记
    我高调的来啦。。。。 花甜的工作笔记
    今天偶听一词云终端 花甜的工作笔记
    我开始出轨了。 花甜的工作笔记
    软件限制策略。。。。。辛苦中。。 花甜的工作笔记
    推荐系统建构精选文章
  • 原文地址:https://www.cnblogs.com/zxporz/p/10870980.html
Copyright © 2020-2023  润新知