if (defaultSerializer == null) {
defaultSerializer = new JdkSerializationRedisSerializer(
classLoader != null ? classLoader : this.getClass().getClassLoader());
}
当然,我们也可以选择Spring Boot Data Redis的其他序列化方案进行配置。
RedisSerializer的实现
在此基础上,我们可以自定义我们自己的序列化方案。
public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
private FastJsonConfig fastJsonConfig = new FastJsonConfig();
private Class<T> type;
public FastJsonRedisSerializer(Class<T> type) {
this.type = type;
}
public FastJsonConfig getFastJsonConfig() {
return fastJsonConfig;
}
public void setFastJsonConfig(FastJsonConfig fastJsonConfig) {
this.fastJsonConfig = fastJsonConfig;
}
@Override
public byte[] serialize(T t) throws SerializationException {
if (t == null) {
return new byte[0];
}
try {
return JSON.toJSONBytes(
fastJsonConfig.getCharset(),
t,
fastJsonConfig.getSerializeConfig(),
fastJsonConfig.getSerializeFilters(),
fastJsonConfig.getDateFormat(),
JSON.DEFAULT_GENERATE_FEATURE,
fastJsonConfig.getSerializerFeatures()
);
} catch (Exception ex) {
throw new SerializationException("Could not serialize: " + ex.getMessage(), ex);
}
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
if (bytes == null || bytes.length == 0) {
return null;
}
try {
return (T) JSON.parseObject(
bytes,
fastJsonConfig.getCharset(),
type,
fastJsonConfig.getParserConfig(),
fastJsonConfig.getParseProcess(),
JSON.DEFAULT_PARSER_FEATURE,
fastJsonConfig.getFeatures()
);
} catch (Exception ex) {
throw new SerializationException("Could not deserialize: " + ex.getMessage(), ex);
}
}
}
当然,这个是基于fastjson的序列化方案,不仅提供了相比于JDK序列化更小的体积,序列化和反序列化的速度上也更快。
这里就粘贴相关代码了,详情可见
https://gitee.com/SoftMeng/spring-boot-skill/tree/master/redis-serializer-line
JDK、FastJson、FST、Kryo测试结果如下,测试项目可见
https://gitee.com/SoftMeng/spring-boot-skill/tree/master/redis-serializer-line
原生JDK序列化方案[序列化100000次]耗时:2160 ms, 大小 44000000
原生JDK序列化方案[序列化100000次]耗时:1406 ms, 大小 44000000
FastJson序列化方案[序列化100000次]耗时:679 ms, 大小 18800000
FastJson序列化方案[序列化100000次]耗时:289 ms, 大小 18800000
FST序列化方案[序列化100000次]耗时:273 ms, 大小 10400000
FST序列化方案[序列化100000次]耗时:130 ms, 大小 10400000
Kryo序列化方案[序列化100000次]耗时:498 ms, 大小 14000000
Kryo序列化方案[序列化100000次]耗时:215 ms, 大小 14000000
FST和Kryo提供了更小的体积和更快的序列化速度,比Fastjson更有性能优势。但是需要提前将需要序列化的对象进行register,这增加了编码难度。而Kryo线程不安全,更需要进行处理,比如通过KryoPool进行池化处理。
通过更换序列化方案,可以解决Redis IO压力过大的问题,提升性能。
Dubbo的项目中提供了大量的序列化方案,在IO传输中体积小,速度快,所以在微服务领域比Spring Cloud更具有性能优势。我们在实现序列化是可以参考以下Dubbo的源码进行编码,毕竟千锤百炼的代码很有借鉴价值。
比如,Dubbo在FST的创建时,会对需要序列化的对象进行 registerClass, 这会显著的增强性能。而在使用Kryo时,不仅register序列化的对象,还需要针对基本类型进行register。
FST 本身已经对基本类型进行注册了,所以FST在易用性上比Kryo更有优势,也提供了@Version对POJO的新增字段进行版本管理。
public FstFactory() {
SerializableClassRegistry.getRegisteredClasses().keySet().forEach(conf::registerClass);
}
public Kryo create() {
if (!kryoCreated) {
kryoCreated = true;
}
Kryo kryo = new CompatibleKryo();
// TODO
// kryo.setReferences(false);
kryo.setRegistrationRequired(registrationRequired);
kryo.addDefaultSerializer(Throwable.class, new JavaSerializer());
kryo.register(Arrays.asList("").getClass(), new ArraysAsListSerializer());
kryo.register(GregorianCalendar.class, new GregorianCalendarSerializer());
kryo.register(InvocationHandler.class, new JdkProxySerializer());
kryo.register(BigDecimal.class, new DefaultSerializers.BigDecimalSerializer());
kryo.register(BigInteger.class, new DefaultSerializers.BigIntegerSerializer());
kryo.register(Pattern.class, new RegexSerializer());
kryo.register(BitSet.class, new BitSetSerializer());
kryo.register(URI.class, new URISerializer());
kryo.register(UUID.class, new UUIDSerializer());
UnmodifiableCollectionsSerializer.registerSerializers(kryo);
SynchronizedCollectionsSerializer.registerSerializers(kryo);
// now just added some very common classes
// TODO optimization
kryo.register(HashMap.class);
kryo.register(ArrayList.class);
kryo.register(LinkedList.class);
kryo.register(HashSet.class);
kryo.register(TreeSet.class);
kryo.register(Hashtable.class);
kryo.register(Date.class);
kryo.register(Calendar.class);
kryo.register(ConcurrentHashMap.class);
kryo.register(SimpleDateFormat.class);
kryo.register(GregorianCalendar.class);
kryo.register(Vector.class);
kryo.register(BitSet.class);
kryo.register(StringBuffer.class);
kryo.register(StringBuilder.class);
kryo.register(Object.class);
kryo.register(Object[].class);
kryo.register(String[].class);
kryo.register(byte[].class);
kryo.register(char[].class);
kryo.register(int[].class);
kryo.register(float[].class);
kryo.register(double[].class);
for (Class clazz : registrations) {
kryo.register(clazz);
}
SerializableClassRegistry.getRegisteredClasses().forEach((clazz, ser) -> {
if (ser == null) {
kryo.register(clazz);
} else {
kryo.register(clazz, (Serializer) ser);
}
});
return kryo;
}
琐碎时间想看一些技术文章,可以去公众号菜单栏翻一翻我分类好的内容,应该对部分童鞋有帮助。同时看的过程中发现问题欢迎留言指出,不胜感谢~。另外,有想多了解哪些方面内容的可以留言(什么时候,哪篇文章下留言都行),附菜单栏截图(PS:很多人不知道公众号菜单栏是什么),欢迎关注
如果您发现该资源为电子书等存在侵权的资源或对该资源描述不正确等,可点击“私信”按钮向作者进行反馈;如作者无回复可进行平台仲裁,我们会在第一时间进行处理!
加入交流群
请使用微信扫一扫!