SpringBoot2.x—自定义Protostuff方式的RedisSerializer

SpringBoot2.X整合Redis缓存
SpringBoot2.x集成SpringCache+Redis

1. 如何实现自定义ProtostuffRedisSerializer

在SpringBoot2.x环境下,若想使用Redis作为缓存,我们势必要选择一种合适的序列化工具。Redis提供了一个公共接口org.springframework.data.redis.serializer.RedisSerializer。来完成数据的序列化和反序列化。

public interface RedisSerializer {

    @Nullable
    byte[] serialize(@Nullable T t) throws SerializationException;

    @Nullable
    T deserialize(@Nullable byte[] bytes) throws SerializationException;

    static RedisSerializer java() {
        return java(null);
    }

    static RedisSerializer java(@Nullable ClassLoader classLoader) {
        return new JdkSerializationRedisSerializer(classLoader);
    }

    static RedisSerializer json() {
        return new GenericJackson2JsonRedisSerializer();
    }

    static RedisSerializer string() {
        return StringRedisSerializer.UTF_8;
    }
}

我们若想使用Protostuff作为Redis序列化数据的工具,那么就必须实现该接口。

引入依赖

       
            io.protostuff
            protostuff-runtime
            1.6.0
        

        
            io.protostuff
            protostuff-core
            1.6.0
        

实现接口

public class ProtoStuffRedisSerializer implements RedisSerializer {

    private static final Schema schema = RuntimeSchema.getSchema(ObjectWrapper.class);

    @Override
    public byte[] serialize(Object t) throws SerializationException {
        LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
        byte[] bytes;
        try {
            bytes = ProtostuffIOUtil.toByteArray(new ObjectWrapper(t), schema, buffer);
        } finally {
            buffer.clear();
        }
        return bytes;
    }

    @Override
    public Object deserialize(byte[] bytes) throws SerializationException {
        if (bytes == null || bytes.length == 0) {
            return null;
        }
        try {
            ObjectWrapper objectWrapper = new ObjectWrapper();
            ProtostuffIOUtil.mergeFrom(bytes, objectWrapper, schema);
            return objectWrapper.getObject();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static class ObjectWrapper {
        private Object object;

        ObjectWrapper() {
        }

        ObjectWrapper(Object object) {
            this.object = object;
        }

        public Object getObject() {
            return object;
        }

        public void setObject(Object object) {
            this.object = object;
        }
    }
}

2. 性能比较

在Redis的包中,默认提供了几种序列化的工具,如JDK、Jackson、Fastjson等等,我们自定义实现序列化方式性能和官方默认的差距如何呢?

   public void getAccInfoByTime(String customerId, String accType) {
        //获取Bean对象
        Account accInfo = getAccInfo(customerId, accType);
        //JDK的序列化时间
        JdkSerializationRedisSerializer jdk = new JdkSerializationRedisSerializer();
        ProtoStuffRedisSerializer pro = new ProtoStuffRedisSerializer();
        Jackson2JsonRedisSerializer jackson = new Jackson2JsonRedisSerializer(Object.class);
        byte[] jdkBytes = getSerializeTime("JDK序列化", () -> jdk.serialize(accInfo));
        byte[] proBytes = getSerializeTime("PRO序列化", () -> pro.serialize(accInfo));
        byte[] jacksonBytes = getSerializeTime("JACK序列化", () -> jackson.serialize(accInfo));
        Object deserializeTime = getDeserializeTime("JDK反序列化时间:", () -> jdk.deserialize(jdkBytes));
        Object deserializeTime1 = getDeserializeTime("PRO反序列化时间:", () -> pro.deserialize(proBytes));
        Object deserializeTime2 = getDeserializeTime("JACK序列化时间:", () -> jackson.deserialize(jacksonBytes));
    }

    /**
     * 计算序列化的耗时时间
     *
     * @param supplier
     * @return
     */
    private byte[] getSerializeTime(String desc, Supplier supplier) {
        long startTime = System.currentTimeMillis();
        byte[] bytes = supplier.get();
        System.out.println(desc + "时间:" + (System.currentTimeMillis() - startTime) + " ms");
        System.out.println(desc + "大小:" + bytes.length + " b");
        return bytes;
    }


    /**
     * 计算反的耗时时间
     *
     * @param supplier
     * @return
     */
    private Object getDeserializeTime(String desc, Supplier supplier) {
        long startTime = System.currentTimeMillis();
        Object obj = supplier.get();
        System.out.println(desc + (System.currentTimeMillis() - startTime) + " ms");
        return obj;
    }

执行结果:

JDK序列化时间:0 ms
JDK序列化大小:865 b
PRO序列化时间:0 ms
PRO序列化大小:155 b
JACK序列化时间:15 ms
JACK序列化大小:447 b
JDK反序列化时间:1 ms
PRO反序列化时间:0 ms
JACK序列化时间:2 ms

可以看到,protostuff在压缩时间,以及压缩后的大小上都是比较占优的。

文章推荐

CacheManager以及序列化类

你可能感兴趣的:(SpringBoot2.x—自定义Protostuff方式的RedisSerializer)