Redis使用kryo来进行序列化遇到的问题

1.通过spring-data-redis集成redis,使用kryo的方式来序列化value值,kryo是一款高性能的序列化反序列话工具,具体要引入的jar包可以参看

https://mvnrepository.com/artifact/com.esotericsoftware/kryo

需要导入的jar包有


    com.esotericsoftware
    kryo
    4.0.2



    de.javakaffee
    kryo-serializers
    0.42

redis的xml配置方式:

	
		
		
			
		
		
			
				
					com.enjoy.ticket.Ticket
				
			
		
		
			
		
		
			
		
		
	

Kryo的序列化工具类

public class KryoSerializer implements RedisSerializer {

    private static final int BUFFER_SIZE = 2048;

    private Kryo kryo = new Kryo();

    @Override

    public byte[] serialize(T t) throws SerializationException {

        byte[] buffer = new byte[BUFFER_SIZE];

        Output output = new Output(buffer);

        kryo.writeClassAndObject(output, t);

        return output.toBytes();

    }

    @Override

    public T deserialize(byte[] bytes) throws SerializationException {

        Input input = new Input(bytes);

        T t = (T) kryo.readClassAndObject(input);

        return t;

    }

}

照着这种类配置,大约是用不了的,反序列化时会有问题:

问题1:序列化的数据,存在Collections.unmodifiableMap修饰的HashMap,在反序列化时就会出现问题,该Map是只读的,在反序列化后得到了Map但是Map中的数据是没有办法放入到只读Map中的。

所以引入了kryo-serializers的包来处理问题,对kryo对象进行设置:

UnmodifiableCollectionsSerializer.registerSerializers(kryo);

加入这条配置在序列化和反序列化的方法中;

问题2:反序列化报错:Class cannot be created (missing no-arg constructor),这个错误会报出来;

网上说这种解决方式是SynchronizedCollectionsSerializer.registerSerializers(kryo);在序列化和反序列化的方法中加入该配置,也是源于kryo-serializers包的。

项目中使用了另外的方法来解决:

kryo.setInstantiatorStrategy(new Kryo.DefaultInstantiatorStrategy(new StdInstantiatorStrategy()));

最后写出来的kryo的序列化工具类就是如下了:

   public byte[] serialize(T t) throws SerializationException {
        if (t == null) {
            return EMPTY_BYTE_ARRAY;
        }

        Kryo kryo = kryos.get();
        kryo.setInstantiatorStrategy(new Kryo.DefaultInstantiatorStrategy(new StdInstantiatorStrategy()));
        kryo.setReferences(false);
        kryo.register(clazz);
        UnmodifiableCollectionsSerializer.registerSerializers(kryo);

        try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
             Output output = new Output(baos)) {
            kryo.writeClassAndObject(output, t);
            output.flush();
            return baos.toByteArray();
        } catch (Exception e) {
            LOG.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.setInstantiatorStrategy(new Kryo.DefaultInstantiatorStrategy(new StdInstantiatorStrategy()));
        kryo.register(clazz);
        UnmodifiableCollectionsSerializer.registerSerializers(kryo);

        try (Input input = new Input(bytes)) {
            return (T) kryo.readClassAndObject(input);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        }

        return null;
    }

使用的是kryo的4.0.2版本的kryo包,kryo-serializers是0.42版本的,这一版本是要依赖4.0.0或4.0.2版本的kryo包的。

你可能感兴趣的:(java)