FST快速序列化和反序列化, Redis使用FST
2021/9/8 19:09:02
本文主要是介绍FST快速序列化和反序列化, Redis使用FST,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
FST
快速序列化和反序列化
FST: github
参考
参考
介绍
FST的使用有两种方式,一种是快捷方式,另一种需要使用ObjectOutput和ObjectInput。
快捷方式
static void quickStart() { FSTConfiguration conf = FSTConfiguration.createAndroidDefaultConfiguration(); FstObject object = new FstObject(); object.setName("huaijin"); object.setAge(30); System.out.println("serialization, " + object); byte[] bytes = conf.asByteArray(object); FstObject newObject = (FstObject) conf.asObject(bytes); System.out.println("deSerialization, " + newObject); }
直接使用FSTConfiguration提供的序列化和反序列化接口。FSTConfiguration也提供了注册对象的Class接口,如果不注册,默认会将对象的Class Name写入。
这个提供了易用高效的API方式,不使用ByteArrayOutputStreams而直接得到byte[]。
ObjectOutput和ObjectInput
static FSTConfiguration conf = FSTConfiguration.createAndroidDefaultConfiguration(); static void writeObject(OutputStream outputStream, FstObject fstObject) throws IOException { FSTObjectOutput out = conf.getObjectOutput(outputStream); out.writeObject(fstObject); out.close(); } static FstObject readObject(InputStream inputStream) throws Exception { FSTObjectInput input = conf.getObjectInput(inputStream); FstObject fstObject = (FstObject) input.readObject(FstObject.class); input.close(); return fstObject; }
能更细腻控制序列化的写入写出
配置
pom
<!-- 用于序列化和反序列化--> <dependency> <groupId>de.ruedigermoeller</groupId> <artifactId>fst</artifactId> <version>2.57</version> </dependency>
FSTSerializer-fst单例
import org.nustaq.serialization.FSTConfiguration; import org.nustaq.serialization.FSTDecoder; import org.nustaq.serialization.FSTEncoder; import org.nustaq.serialization.coders.FSTStreamDecoder; import org.nustaq.serialization.coders.FSTStreamEncoder; import java.io.IOException; import java.lang.reflect.Field; /** * 使用fts进行序列化 */ public class FSTSerializer { static class FSTDefaultStreamCoderFactory implements FSTConfiguration.StreamCoderFactory { // 单例的生成工厂, // 并且让FSTStreamDecoder.chBufS FSTStreamDecoder.ascStringCache为空 Field chBufField; Field ascStringCacheField; { try { chBufField = FSTStreamDecoder.class.getDeclaredField("chBufS"); ascStringCacheField = FSTStreamDecoder.class.getDeclaredField("ascStringCache"); } catch (Exception e) { throw new IllegalStateException(e); } ascStringCacheField.setAccessible(true); chBufField.setAccessible(true); } private FSTConfiguration fstConfiguration; FSTDefaultStreamCoderFactory(FSTConfiguration fstConfiguration) { this.fstConfiguration = fstConfiguration; } @Override public FSTEncoder createStreamEncoder() { return new FSTStreamEncoder(fstConfiguration); } @Override public FSTDecoder createStreamDecoder() { return new FSTStreamDecoder(fstConfiguration) { @Override public String readStringUTF() throws IOException { try { String res = super.readStringUTF(); chBufField.set(this, null);// xField.set(FSTStreamDecoder obj, Object value) 把FSTStreamDecoder对象的xField设置为value return res; } catch (Exception e) { throw new IOException(e); } } @Override public String readStringAsc() throws IOException { try { String res = super.readStringAsc(); ascStringCacheField.set(this, null); return res; } catch (Exception e) { throw new IOException(e); } } }; } static ThreadLocal input = new ThreadLocal(); static ThreadLocal output = new ThreadLocal(); @Override public ThreadLocal getInput() { return input; } @Override public ThreadLocal getOutput() { return output; } } private static class InstanceHolder { // 生成单例 private static final FSTConfiguration INSTANCE = FSTConfiguration.createDefaultConfiguration(); static { INSTANCE.setStreamCoderFactory(new FSTDefaultStreamCoderFactory(INSTANCE)); } } public FSTConfiguration getConfig() {// 返回单例 return InstanceHolder.INSTANCE; } }
为什么解码之前要清空缓存?
装载: Fst反序列化失败_weixin_33708432的博客-CSDN博客
fst在做反序列化时 由于该数据原先序列化的时候类(可以称之为模板)是有10个字段,但是当开发增加了2个字段后 由于既存的数据中已经均是10个字段的数据(实例)但是事实上新的版本中已经变成12个字段了。
当反序列化时由于根据对应的class信息(没有指定version annotation)导致反序列化报错。
要求必须指定version,如果有需要设置默认值等等可以使用VersionConflictListener那么解决方案也很简单,当增加字段的时候直接将缓存清空即可(避免增加version字段)
FstRedisSerializer-redis使用fst单例
import com.yami.shop.common.serializer.FSTSerializer; import lombok.SneakyThrows; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.lang.Nullable; /** * 使用fst 进行reids的序列化 */ public class FstRedisSerializer implements RedisSerializer<Object> { private static final byte[] EMPTY_ARRAY = new byte[0]; @Override @SneakyThrows public byte[] serialize(Object o) { if (o == null) { return EMPTY_ARRAY; } return new FSTSerializer().getConfig().asByteArray(o); } @Override @SneakyThrows public Object deserialize(byte[] bytes) { if (isEmpty(bytes)) { return null; } return new FSTSerializer().getConfig().asObject(bytes); } private static boolean isEmpty(@Nullable byte[] data) { return (data == null || data.length == 0); } }
FstCodec-redisson使用fst单例
import org.nustaq.serialization.FSTConfiguration; import org.nustaq.serialization.FSTObjectInput; import org.nustaq.serialization.FSTObjectOutput; import org.redisson.client.codec.BaseCodec; import org.redisson.client.handler.State; import org.redisson.client.protocol.Decoder; import org.redisson.client.protocol.Encoder; import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufInputStream; import io.netty.buffer.ByteBufOutputStream; /** * 被redisson使用 * Efficient and speedy serialization codec fully * compatible with JDK Serialization codec. * * https://github.com/RuedigerMoeller/fast-serialization * * @author Nikita Koksharov * */ public class FstCodec extends BaseCodec { private final FSTConfiguration config; public FstCodec() { config = new FSTSerializer().getConfig(); } private final Decoder<Object> decoder = new Decoder<Object>() { @Override public Object decode(ByteBuf buf, State state) throws IOException { ByteBufInputStream in = new ByteBufInputStream(buf); FSTObjectInput inputStream = config.getObjectInput(in); try { return inputStream.readObject(); } catch (IOException e) { throw e; } catch (Exception e) { throw new IOException(e); } } }; private final Encoder encoder = new Encoder() { @Override public ByteBuf encode(Object in) throws IOException { ByteBuf out = ByteBufAllocator.DEFAULT.buffer(); ByteBufOutputStream os = new ByteBufOutputStream(out); FSTObjectOutput oos = config.getObjectOutput(os); try { oos.writeObject(in); oos.flush(); return os.buffer(); } catch (IOException e) { out.release(); throw e; } catch (Exception e) { out.release(); throw new IOException(e); } } }; @Override public Decoder<Object> getValueDecoder() { return decoder; } @Override public Encoder getValueEncoder() { return encoder; } @Override public ClassLoader getClassLoader() { if (config.getClassLoader() != null) { return config.getClassLoader(); } return super.getClassLoader(); } }
这篇关于FST快速序列化和反序列化, Redis使用FST的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-08阿里云Redis项目实战入门教程
- 2024-11-08阿里云Redis资料:新手入门与初级使用指南
- 2024-11-08阿里云Redis教程:新手入门及实用指南
- 2024-11-07阿里云Redis学习入门:新手必读指南
- 2024-11-07阿里云Redis学习入门:从零开始的操作指南
- 2024-11-07阿里云Redis学习:初学者指南
- 2024-11-06阿里云Redis入门教程:轻松搭建与使用指南
- 2024-11-02Redis项目实战:新手入门教程
- 2024-10-22Redis入门教程:轻松掌握数据存储与操作
- 2024-10-22Redis缓存入门教程:快速掌握Redis缓存基础知识