iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >常见Serialize技术有哪些
  • 351
分享到

常见Serialize技术有哪些

2023-06-04 00:06:50 351人浏览 独家记忆
摘要

本篇内容主要讲解“常见Serialize技术有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“常见Serialize技术有哪些”吧!【一、常见的在API及消息通信调的用中Serialize方案

本篇内容主要讲解“常见Serialize技术有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“常见Serialize技术有哪些”吧!

【一、常见的在API及消息通信调的用中Serialize方案】:

方案1、基于Java原生的ObjectOutputStream.write()和ObjectInputStream.read()来进行对象序列化和反序列化。

方案2、基于JSON进行序列化和反序列化。

方案3、基于XML进行序列化和反序列化。

【方案1浅析,ObjectXXXStream】:

优点:

(1)、由Java自带api序列化,简单、方便、无第三方依赖。

(2)、不用担心其中的数据解析会丢失精度、丢失字段、Object的反序列化类型不确定等问题。

缺点:

(1)、双方调试麻烦,发送方和接收方最好是同版本的对象描述,否则会有奇怪的问题,调试周期相对长,跨团队合作升级问题很多。

(2)、传递的对象中包含了元数据信息,占用空间较大。

【方案2浅析,JSON序列化】:

优点:

(1)、简单、方便,无需关注要序列化的对象格式。

(2)、开源界有较多的组件可以支持,例如FastjsON性能非常好。

(3)、在现在很多rpc框架中,基本都支持这样的方案。

缺点:

(1)、对象属性中如果包含Object类型,在反序列化的时候如果业务也本身也不明确数据类型,处理起来会很麻烦。

(2)、由于文本类型,所以一定会占用较大的数据空间,例如下图。

(3)、比较比较依赖于JSON的解析包的兼容性和性能,在JSON的一些细节处理上(例如一些非标的JSON),各自处理方式可能不一样。

(4)、序列化无论任何数据类型先要转换为String,转成byte[],会增加内存拷贝的次数。

(5)、反序列化的时候,必须将整个JSON反序列化成对象后才能进行读取,大家应该知道,Java对象尤其是层次嵌套较多的对象,占用的内存空间将会远远大于数据本身的空间。

数据放大的极端案例1:

传递数据描述信息为:

class PP {

    long userId                       = 102333320132133L;

    int    passportNumber      = 123456;

}

此时传递JSON的格式为:

{

     "userId":102333320132133,

     "passportNumber":123456

}

我们要传递的数据是1个long、1个int,也就是12个字节的数据,这个JSON的字符串长度将是实际的字节数(不包含回车、空格,这里只是为了可读性,同时注意,这里的long在JSON里面是字符串了),这个字符串有:51个字节,也就是数据放到了4.25倍左右。

数据放大极端案例2:

当你的对象内部有数据是byte[]类型,JSON是文本格式的数据,是无法存储byte[]的,那么要序列化这样的数据,只有一个办法就是把byte转成字符,通常的做法有两种:

(1)使用BASE64编码,目前JSON中比较常用的做法。

(2)按照字节进行16进制字符编码,例如字符串:“FF”代表的是0xFF这个字节。

不论上面两种做法的那一种,1个字节都会变成2个字符来传递,也就是byte[]数据会被放大2倍以上。为什么不用ISO-8859-1的字符来编码呢?因为这样编码后,在最终序列化成网络byte[]数据后,对应的byte[]虽然没变大,但是在反序列化成文本的时候,接收方并不知道是ISO-8859-1,还会用例如GBK、UTF-8这样比较常见的字符集解析成String,才能进一步解析JSON对象,这样这个byte[]可能在编码的过程中被改变了,要处理这个问题会非常麻烦。

【方案2浅析,XML序列化】:

优点:

(1)、使用简单、方便,无需关注要序列化的对象格式

(2)、可读性较好,XML在业界比较通用,大家也习惯性在配置文件中看到XML的样子

(3)、大量RPC框架都支持,通过XML可以直接形成文档进行传阅

缺点:

(1)、在序列化和反序列化的性能上一直不是太好。

(2)、也有与JSON同样的数据类型问题,和数据放大的问题,同时数据放大的问题更为严重,同时内存拷贝次数也和JSON类型,不可避免。

XML数据放大说明:

XML的数据放大通常比JSON更为严重,以上面的JSON案例来讲,XML传递这份数据通常会这样传:

<Msg>

     <userId>102333320132133</userId>

     <passportNumber>123456<passportNumber>

<Msg>

这个消息就有80+以上的字节了,如果XML里面再搞一些Property属性,对象再嵌套嵌套,那么这个放大的比例有可能会达到10倍都是有可能的,因此它的放大比JSON更为严重,这也是为什么现在越来越多的API更加喜欢用JSON,而不是XML的原因。

【放大的问题是什么】:

(1)、花费更多的时间去拼接字符串和拷贝内存,占用更多的Java内存,产生更多的碎片。

(2)、产生的JSON对象要转为byte[]需要先转成String文本再进行byte[]编码,因为这本身是文本协议,那么自然再多一次内存全量的拷贝。

(3)、传输过程由于数据被放大,占用更大的网络流量。

(4)、由于网络的package变多了,所以tcp的ACK也会变多,自然系统也会更大,同等丢包率的情况下丢包数量会增加,整体传输时间会更长,如果这个数据传送的网络延迟很大且丢包率很高,我们要尽量降低大小;压缩是一条途径,但是压缩会带来巨大的CPU负载提高,在压缩前尽量降低数据的放大是我们所期望的,然后传送数据时根据RT和数据大小再判定是否压缩,有必要的时候,压缩前如果数据过大还可以进行部分采样数据压缩测试压缩率。

(5)、接收方要处理数据也会花费更多的时间来处理。

(6)、由于是文本协议,在处理过程中会增加开销,例如数字转字符串,字符串转数字;byte[]转字符串,字符串转byte[]都会增加额外的内存和计算开销。

不过由于在平时大量的应用程序中,这个开销相对业务逻辑来讲简直微不足道,所以优化方面,这并不是我们关注的重点,但面临一些特定的数据处理较多的场景,即核心业务在数据序列化和反序列化的时候,就要考虑这个问题了,那么下面我继续讨论问题。

此时提出点问题:

(1)、网络传递是不是有更好的方案,如果有,为什么现在没有大面积采用?

(2)、相对底层的数据通信,例如JDBC是如何做的,如果它像上面3种方案传递结果集,会怎么样?

【二、MySQL JDBC数据传递方案】:

在前文中提到数据在序列化过程被放大数倍的问题,我们是否想看看一些相对底层的通信是否也是如此呢?那么我们以Mysql JDBC为例子来看看它与JDBC之间进行通信是否也是如此。

JDBC驱动程序根据数据库不同有很多实现,每一种数据库实现细节上都有巨大的区别,本文以mysql JDBC的数据解析为例(Mysql 8.0以前),给大家说明它是如何传递数据的,而传递数据的过程中,相信大家最为关注的就是ResultSet的数据是如何传递的。

抛开结果集中的MetaData等基本信息,单看数据本身:

(1)JDBC会读取数据行的时候,首先会从缓冲区读取一个row packege,row package就是从网络package中拿到的,根据协议中传递过来的package的头部判定package大小,然后从网络缓冲中读取对应大小的内容,下图想表达网络传递的package和业务数据中的package之间可能并不是完全对应的。另外,网络中的package如果都到了本地缓冲区,逻辑上讲它们是连续的(图中故意分开是让大家了解到网络中传递是分不同的package传递到本地的),JDBC从本地buffer读取row package这个过程就是内核package到JVM的package拷贝过程,对于我们Java来讲,我们主要关注row package(JDBC中可能存在一些特殊情况读取过来的package并不是行级别的,这种特殊情况请有兴趣的同学自行查阅源码)。

我们先不考虑按照bit有31个bit是0,先按照字节来看有7个0,代表字节没有数据,只有1个字节是有值的,大家可以去看一下自己的数据库中大量的自动增长列,在id小于4194303之前,前面5个字节是浪费掉的,在增长到4个字节(2的32次方-1)之前前面4个自己都是0,浪费掉的。另外,即使8个字节中的第一个字节开始使用,也会有大量的数据,中间字节是为:0的概率极高,就像十进制中进入1亿,那么1亿下面最多会有8个0,越高位的0约难补充上去。

如果真的想去尝试,可以用这个办法:用1个字节来做标志,但会占用一定的计算开销,所以是否为了这个空间去做这个事情,由你决定,本文仅仅是技术性探讨:

方法1:表达目前有几个低位被使用的字节数,由于long只有8个字节,所以用3个bit就够了,另外5个bit是浪费掉的,也无所谓了,反序列化的时候按照高位数量补充0x00即可。

方法2:相对方法1,更彻底,但处理起来更复杂,用1这个字节的8个bit的0、1分别代表long的8个字节是被使用,序列化和反序列化过程根据标志位和数据本身进行字节补0x00操作,补充完整8个字节就是long的值了,最坏情况是9个字节代表long,最佳情况0是1个字节,字节中只占用了2个字节的时候,即使数据变得相当大,也会有大量的数据的字节存在空位的情况,在这些情况下,就通常可以用少于8个字节的情况来表达,要用满7个字节才能够与原数字long的占用空间一样,此时的数据已经是比2的48次方-1更大的数据了。

【三、Google Protocol Buffer技术方案】:

这个对于很多人来讲未必用过,也不知道它是用来干什么的,不过我不得不说,它是目前数据序列化和反序列化的一个神器,这个东西是在谷歌内部为了约定好自己内部的数据通信设计出来的,大家都知道谷歌的全球网络非常牛逼,那么自然在数据传输方面做得那是相当极致,在这里我会讲解下它的原理,就本身其使用请大家查阅其它人的博客,本文篇幅所限没法step by step进行讲解。

看到这个名字,应该知道是协议Buffer,或者是协议编码,其目的和上文中提到的用JSON、XML用来进行RPC调用类似,就是系统之间传递消息或调用API。但是谷歌一方面为了达到类似于XML、JSON的可读性和跨语言的通用性,另一方面又希望达到较高的序列化和反序列化性能,数据放大能够进行控制,所以它又希望有一种比底层编码更容易使用,而又可以使用底层编码的方式,又具备文档的可读性能力。

它首先需要定义一个格式文件,如下:

syntax = "proto2";

package com.xxx.proto.buffer.test;

message TestData2 {
   optional int32 id = 2;
   optional int64 longId = 1;
   optional bool  boolValue = 3;
   optional string name = 4;
   optional bytes bytesValue = 5;
   optional int32 id2 = 6;
}

这个文件不是Java文件,也不是C文件,和语言无关,通常把它的后缀命名为proto(文件中1、2、3数字代表序列化的顺序,反序列化也会按照这个顺序来做),然后本地安装了protobuf后(不同OS安装方式不同,在官方有下载和说明),会产生一个protoc运行文件,将其加入环境变量后,运行命令指定一个目标目录:

protoc --java_out=~/temp/ TestData2.proto

此时会在指定的目录下,产生package所描述的目录,在其目录内部有1个Java源文件(其它语言的会产生其它语言),这部分代码是谷歌帮你生成的,你自己写的话太费劲,所以谷歌就帮你干了;本地的Java project里面要引入protobuf包,Maven引用(版本自行选择):

<dependency>

     <groupId>com.google.protobuf</groupId>

    <artifactId>protobuf-java</artifactId>

    <version>3.6.1</version>

</dependency>

此时生成的代码会调用这个谷歌包里面提供的方法库来做序列化动作,我们的代码只需要调用生成的这个类里面的API就可以做序列化和反序列化操作了,将这些生成的文件放在一个模块里面发布到maven仓库别人就可以引用了,关于测试代码本身,大家可以参考目前有很多博客有提供测试代码,还是很好用的。

谷歌编码比较神奇的是,你可以按照对象的方式定义传输数据的格式,可读性极高,甚至于相对XML和JSON更适合程序员阅读,也可以作为交流文档,不同语言都通用,定义的对象还是可以嵌套的,但是它序列化出来的字节比原始数据只大一点点,这尼玛太厉害了吧。

经过测试不同的数据类型,故意制造数据嵌套的层数,进行二进制数组多层嵌套,发现其数据放大的比例非常非常小,几乎可以等价于二进制传输,于是我把序列化后的数据其二进制进行了输出,发现其编码方式非常接近于上面的JDBC,虽然有一些细节上的区别,但是非常接近,除此之外,它在序列化的时候有几大特征:

(1)、如果字段为空,它不会产生任何字节,如果整合对象的属性都为null,产生的字节将是0

(2)、对int32、int64这些数据采用了变长编码,其思路和我们上面描述有一些共通之处,就是一个int64值在比较小的时候用比较少的字节就可以表达了,其内部有一套字节的移位和异或算法来处理这个事情。

(3)、它对字符串、byte[]没有做任何转换,直接放入字节数组,和二进制编码是差不多的道理。

(4)、由于字段为空它都可以不做任何字节,它的做法是有数据的地方会有一个位置编码信息,大家可以尝试通过调整数字顺序看看生成出来的byte是否会发生改变;那么此时它就有了很强兼容性,也就是普通的加字段是没问题的,这个对于普通的二进制编码来讲很难做到。

(5)、序列化过程没有产生metadata信息,也就是它不会把对象的结构写在字节里面,而是反序列化的接收方有同一个对象,就可以反解析出来了。

这与我自己写编码有何区别?

(1)、自己写编码有很多不确定性,写不好的话,数据可能放得更大,也容易出错。

(2)、Google的工程师把内部规范后,谷歌开源的产品也大量使用这样的通信协议,越来越多的业界中间件产品开始使用该方案,就连MySQL数据库最新版本在数据传输方面也会开始兼容protobuf。

(3)、谷歌相当于开始在定义一个业界的新的数据传输方案,即有性能又降低代码研发的难度,也有跨语言访问的能力,所以才会有越来越多的人喜欢使用这个东西。

那么它有什么缺点呢?还真不多,它基本兼顾了很多序列化和反序列化中你需要考虑的所有的事情,达到了一种非常良好的平衡,但是硬要挑缺陷,我们就得找场景才行:

(1)、protobuf需要双方明确数据类型,且定义的文件中每一个对象要明确数据类型,对于Object类型的表达没有方案,你自己必须提前预知这个Object到底是什么类型。

(2)、使用repeated可以表达数组,但是只能表达相同类型的数据,例如上面提到的JDBC一行数据的多个列数据类型不同的时候,要用这个表达,会比较麻烦;另外,默认情况下数组只能表达1维数组,要表达二维数组,需要使用对象嵌套来间接完成。

(3)、它提供的数据类型都是基本数据类型,如果不是普通类型,要自己想办法转换为普通类型进行传输,例如从MongoDB查处一个Docment对象,这个对象序列化是需要自己先通过别的方式转换为byte[]或String放进去的,而相对XML、JSON普通是提供了递归的功能,但是如果protobuf要提供这个功能,必然会面临数据放大的问题,通用和性能永远是矛盾的。

(4)、相对于自定义byte的话,序列化和反序列化是一次性完成,不能逐步完成,这样如果传递数组嵌套,在反序列化的时候会产生大量的Java对象,另外自定义byte的话可以进一步减少内存拷贝,不过谷歌这个相对文本协议来讲内存拷贝已经少很多了。

到此,相信大家对“常见Serialize技术有哪些”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: 常见Serialize技术有哪些

本文链接: https://www.lsjlt.com/news/235973.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 常见Serialize技术有哪些
    本篇内容主要讲解“常见Serialize技术有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“常见Serialize技术有哪些”吧!【一、常见的在API及消息通信调的用中Serialize方案...
    99+
    2023-06-04
  • CSS常见技术有哪些
    这篇文章主要介绍了CSS常见技术有哪些的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇CSS常见技术有哪些文章都会有所收获,下面我们一起来看看吧。1、介绍一下标准的 CSS 的盒...
    99+
    2024-04-02
  • 常见负载均衡技术有哪些
    常见的负载均衡技术有以下几种:1. 随机负载均衡:随机选择一台服务器来处理请求,简单易实现,但可能导致负载不均衡。2. 轮询负载均衡...
    99+
    2023-09-02
    负载均衡
  • Linux面试中常见的PHP缓存技术有哪些?
    在现代Web应用程序开发中,缓存技术已经成为了必不可少的一部分。缓存技术可以提高应用程序的性能,减少数据库的负担,从而提高Web应用程序的响应速度和用户体验。在PHP开发中,缓存技术也是非常重要的。在Linux面试中,面试官经常会问到PH...
    99+
    2023-09-14
    缓存 面试 linux
  • CSS常见的技巧有哪些
    本篇内容主要讲解“CSS常见的技巧有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“CSS常见的技巧有哪些”吧!如何清除图片下方出现几像素的空白间隙? 代码如下:方法1: img{displa...
    99+
    2023-06-08
  • SQL Server中有哪些常见术语
    本篇文章给大家分享的是有关SQL Server中有哪些常见术语,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。BEGIN TRANSACTION...
    99+
    2024-04-02
  • Golang 技术性能优化中的常见陷阱有哪些?
    避免 go 语言性能优化中的陷阱:过早优化:在基准测试确定瓶颈前避免优化。过度使用 goroutine:明智地使用 goroutine,考虑替代的并发机制。不正确的内存分配:避免重复分配...
    99+
    2024-05-11
    golang 技术优化
  • 数据库中常见术语有哪些
    这篇文章将为大家详细讲解有关数据库中常见术语有哪些,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。Access数据库中有一些常见的术语,下面是小编为大家总结的...
    99+
    2024-04-02
  • php常用缓存技术有哪些
    在PHP中,常用的缓存技术有以下几种:1. 文件缓存:将数据以文件的形式存储在服务器的文件系统中。可以使用PHP的文件操作函数(如f...
    99+
    2023-08-24
    php
  • 常见的HTML优化技巧有哪些
    这篇文章主要介绍了常见的HTML优化技巧有哪些的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇常见的HTML优化技巧有哪些文章都会有所收获,下面我们一起来看看吧。很显然HTML ...
    99+
    2024-04-02
  • 常见的PHP魔术方法类有哪些
    这篇文章主要讲解了“常见的PHP魔术方法类有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“常见的PHP魔术方法类有哪些”吧!__construct()方法__construct()方法是...
    99+
    2023-07-05
  • 常见的pycharm使用技巧有哪些
    1. 快捷键操作:掌握常用的快捷键可以提高工作效率,如Ctrl + S保存文件、Ctrl + Shift + F查找替换、Ctrl ...
    99+
    2023-09-20
    pycharm
  • HTLM技术的常规语义有哪些
    这篇文章主要介绍“HTLM技术的常规语义有哪些”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“HTLM技术的常规语义有哪些”文章能帮助大家解决问题。1.换行此标记用于...
    99+
    2024-04-02
  • 常用的web前端技术有哪些
    常用的Web前端技术包括:1. HTML:网页结构标记语言,用于定义网页的结构和内容。2. CSS:层叠样式表,用于定义网页的样式和...
    99+
    2023-06-12
    web前端技术 web前端
  • 常州网站建设技术有哪些
    常州网站建设技术包括:1. HTML/CSS技术:用于网站的基础结构和样式设计。2. JavaScript技术:用于网站的交互效果和...
    99+
    2023-06-12
    常州网站建设 网站建设
  • Navicat中常见的使用技巧有哪些
    这篇文章主要介绍Navicat中常见的使用技巧有哪些,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!常用的Navicat的使用技巧:以上是“Navicat中常见的使用技巧有哪些”这篇文...
    99+
    2024-04-02
  • JavaScript数组常见操作技巧有哪些
    这篇文章主要介绍“JavaScript数组常见操作技巧有哪些”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“JavaScript数组常见操作技巧有哪些”文章能帮助大家解决问题。一、创建数组创建数组是基...
    99+
    2023-06-29
  • oracle技术有哪些
    oracle 技术是一套用于管理和分析数据的软件,包括 oracle 数据库、应用程序、云基础设施和中间件。它提供高性能、可靠性、成本效益、全面的工具和社区支持。 Oracle 技术 ...
    99+
    2024-04-19
    oracle
  • LINQ技术有哪些
    这篇文章主要介绍了LINQ技术有哪些,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。.NET Language-Integrated Query(LINQ,语言集成查询)是微软...
    99+
    2023-06-17
  • ajax技术有哪些
    1. XMLHttpRequest:最早的Ajax技术,通过JavaScript创建一个XMLHttpRequest对象,发送HTT...
    99+
    2023-08-29
    ajax
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作