首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

教妹子学序列化kryo的经历

女同事的疑问

:老哥,为什么你的接口那么快呢?

我故作镇定的回答:妹子,因为咱俩序列化的方式不同。

:流弊篓子,你用的什么方式呀?

我撩了一下稀疏而飘逸的头发说:我用的kryo啊,大妹砸。

:老哥可以教教我吗?(应该是被我帅气的外表迷倒了)

我装做很不情愿的样子回答:那行吧,就这一次啊。来,哥教你

。。。诶,别走啊,我还没开始讲呢!

何为序列化 / 反序列化

序列化

序列化就是一种处理的机制。

即将对象的内容流化,将数据转化成,以便存储在中或用于在中传输,当然用的最多的肯定就是。

反序列化

从中或上获得序列化后的对象字节流后,根据字节流中所保存的对象状态及描述信息,通过反序列化。

大家所常见的序列化/反序列化的方式:。

谁敢说没见过Serializable,。

JDK提供的Serializable速度较慢,原因比如:因为加入了序列化版本号,类名等信息,所以导致码流变大,速度变慢等等。

所以我们要来学一些速度快的序列化方式。不仅速度快,占用的空间还小。

这么好的技术,那个妹子没学到,真是可惜了。

序列化选型标准

通用性:是否只能用于java间序列化/反序列化,是否跨语言、跨平台

性能:分为空间开销和时间开销,序列化后的数据一般用于存储或网络传输,其大小是很重要的一个参数;

当然解析的时间也影响了序列化协议的选择

易用性:API使用是否复杂,是否影响开发效率

可扩展性:实体类的属性变更会不会导致反序列化异常,这通常会在系统升级时会产生,参考性不是很大

Kryo序列化入门

Kryo 是一个快速序列化/反序列化工具,其使用了字节码生成机制(底层依赖了 ASM 库),因此具有比较好的运行速度。

Kryo 序列化出来的结果,是其自定义的、独有的一种格式,不再是 JSON 或者其他现有的通用格式;

而且,其序列化出来的结果是二进制的(即 byte[];而 JSON 本质上是字符串 String);

二进制数据显然体积更小,序列化、反序列化时的速度也更快。

Kryo 一般只用来进行序列化(然后作为缓存,或者落地到存储设备之中)、反序列化,而不用于在多个系统、甚至多种语言间进行数据交换 —— 目前 kryo 也只有 java 实现。

像Redis这样的存储工具,是可以安全的存储二进制数据,所以一般项目中可使用Kryo来替代JDK序列化进行存储。

:(数据交换或数据持久化)比如使用kryo把对象序列化成字节数组发送给消息队列或者放到redis等nosql中等等应用场景。

pom配置

需要注意的是,由于kryo使用了较高版本的asm,可能会与业务现有依赖的asm产生冲突,这是一个比较常见的问题。只需将依赖改成:

代码实现

:由于kryo不是线程安全的,针对多线程情况下的使用,要对kryo进行一个简单的封装设计,从而可以多线程安全的使用序列化和反序列化

接口

实现类

Kryo的IO

Kryo致力以简单易用的API,序列化过程中主要核心有、、。

Output和Input是Kryo的,他们支持以或者的形式为序列化的dest和反序列化的source。

当使用stream形式进行写出写入时,需要close这些Output和Input。

写出时,当OutputDe buffer是满的时候,就会flush bytes到stream中。

写入时,会从stream中获取bytes到Input buffer中,当填充满时,进行反序列化。

Kryo的注册

和很多其他的序列化框架一样,Kryo为了提供性能和减小序列化结果体积,提供注册的序列化对象类的方式。

在注册时,会为该序列化类生成int ID,后续在序列化时使用int ID唯一标识该类型。

注册的方式如下:

或者可以明确指定注册类的int ID,但是该ID必须大于等于0。如果不提供,内部将会使用int++的方式维护一个有序的int ID生成。

对象引用方面

这是对循环引用的支持,可以有效防止栈内存溢出,kryo默认会打开这个属性。

当你确定不会有循环引用发生的时候,可以通过以下代码关闭循环引用检测,从而提高一些性能,但不是很推荐

Kryo的读和写的方式

如果序列化的对象类型未知并且可能为空:

如果对象类型已知并且可能为空:

如果对象类型已知并且不可能为空:

序列化线程安全

Kryo默认是线程不安全的,有两种解决方式:

一个是通过Threadlocal的方式为某个线程存储一个实例:

另外一种是通过KryoPool的方式,该方式在性能上也好于ThreadLocal:

kryo支持序列化的类型

kryo优缺点总结

优点

序列化的性能非常高

序列化结果体积较小

提供了简单易用的API

缺点

跨语言支持较复杂

不支持对象字段的增加/删除/修改

如果更改了对象的字段,然后再从更改前序列化的bytes中反序列化,将会出错。

当然如果想得到Add、Remove等操作的支持,可以使用FieldSerializer的其他扩展,如、等等。

kryo 与 JDK性能对比

Simple类

JDK性能测试

kryo性能测试

测试结果

JDK

java原生序列化时间:6614 ms

java原生反序列化时间:8609 ms

kryo

Kryo 序列化时间:757 ms

Kryo 反序列化时间:307 ms

给个[在看],是对IT老哥最大的支持

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20201027A01J6W00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券