目录
一、概述
数据序列化:数据序列化是将内存对象转化为字节流的过程,它直接决定了数据解析效率以及模式演化能力(数据格式发生变化时,比如增加或删除字段,是否仍能够保持兼容性)。
二、数据序列化的意义
当需要将数据存入文件或者通过网络发送出去时,需将数据对象转化为字节流,即对数据序列化。考虑到性能、占用空间以及兼容性等因素,我们通常会经历以下几个阶段的技术演化,最终找到解决该问题的最优方案:
阶段 1:不考虑任何复杂的序列化方案,直接将数据转化成字符串,以文本形式保存或传输,如果一条数据存在多个字段,则使用分隔符(比如“,”)。该方案存储简单数据绰绰有余,但对于复杂数据,且数据模式经常变动时,将变得非常繁琐,通常会面临以下问题。
(1)难以表达嵌套数据:如果每条数据是嵌套式的,比如类似于map,list数据结构时,以文本方式存储是非常困难的。
(2)无法表达二进制数据:图片、视频等二进制数据无法表达,因为这类数据无法表达成简单的文本字符串。
(3)难以应对数据模式变化:在实际应用过程中,由于用户考虑不周全或需求发生变化,数据模式可能会经常发生变化。而每次发生变化,之前所有写入和读出(解析)模块均不可用,所有解析程序均需要修改,非常繁琐。
阶段 2:采用编程语言内置的序列化机制,比如 Java Serialization,Python pickle 等。这种方式解决了阶段 1 面临的大部分问题,但随着使用逐步深入,可以发现这种方式将数据表示方式跟某种特定语言绑定在一起,很难做到跨语言数据的写入和读取。
阶段 3:为了解决阶段 2 面临的问题,我们决定使用应用范围广、跨语言的数据表示格式,比如JSON 和 XML。但使用一段时间后,你会发现这种方式存在严重的性能问题:解析速度太慢,同时数据存储冗余较大,比如JSON会重复存储每个属性的名称等。
阶段 4:到这一阶段,我们期望出现一种带有schema描述的数据表示格式,通过统一化的schema描述,可约束每个字段的类型,进而为存储和解析数据带来优化的可能。此外,统一schema的引入,可减少属性名称重复存储带来的开销,同时,也有利于数据共享。
阶段 4 提到的方式便是序列化框架,常用的有 Thrift,Protocol Buffers 和 Avro,它们被称为“Language Of Data”。它们通过引入 schema,使得数据跨序列化变得非常高效,同时提供了代码生成工具,为用户自动生成各种语言的代码。总结起来,“Language Of Data”具备以下基本特征:
(1)提供 IDL(Interface Description language)用以描述数据 schema,能够很容易地描述任意结构化数据和非结构化数据。
(2)支持跨语言读写,至少支持 C++、Java 和 Python 三种主流语言。
(3)数据编码存储(整数可采用变长编码,字符串可采用压缩编码等),以尽可能避免不必要的存储浪费。
(4&#