[TOC]

文章参考:https://zhuanlan.zhihu.com/p/505338692

概述

没有一种序列化方案能像JSON和XML一样流行,自由、方便,拥有强大的表达力和跨平台能力。是通用数据传输格式的默认首选。不过随着数据量的增加和性能要求的提升,这种自由与通用带来的性能问题也不容忽视。

JSON和XML使用字符串表示所有的数据,对于非字符数据来说,字面量表达会占用很多额外的存储空间,并且会严重受到数值大小和精度的影响。 一个32位浮点数 1234.5678 在内存中占用 4 bytes 空间,如果存储为 utf8 ,则需要占用 9 bytes空间,在JS这样使用utf16表达字符串的环境中,需要占用 18 bytes空间。 使用正则表达式进行数据解析,在面对非字符数据时显得十分低效,不仅要耗费大量的运算解析数据结构,还要将字面量转换成对应的数据类型。

在面对海量数据时,这种格式本身就能够成为整个系统的IO与计算瓶颈,甚至直接overflow。

众多的序列化方案中,按照存储方案,可分为字符串存储和二进制存储,字符串存储是可读的,但是由于以上问题,这里只考虑二进制存储。二进制存储中可分为需要IDL和不需要IDL,或分为自描述与非自描述(反序列化是否需要IDL)。

需要IDL的使用过程:

  • 使用该方案所定义的IDL语法编写schema
  • 使用该方案提供的编译器将schema编译成生产方和消费方所用语言的代码(类或者模块)
  • 数据生产方引用该代码,根据其接口,构建数据,并序列化
  • 消费方引用该代码,根据其接口读取数据

不需要IDL的使用过程:

  • 生产方与消费方通过文档约定数据结构
  • 生产方序列化
  • 消费方反序列化

例如:

  • protocol buffers

    • gRPC所用的传输协议,二进制存储,需要IDL,非自描述
    • 高压缩率,表达性极强,在Google系产品中使用广泛
  • flat buffers

    • Google推出序列化方案,二进制存储,需要IDL,非自描述(自描述方案不跨平台)
    • 高性能,体积小,支持string、number、boolean
  • avro

    • Hadoop使用的序列化方案,将二进制方案和字符串方案的优势结合起来,仅序列化过程需要IDL,自描述
    • 然而场景受限,没有成熟的JS实现,不适合Web环境,这里不做对比
  • Thrift

    • Facebook的方案,二进制存储,需要IDL,非自描述
    • 基本上只集成在RPC中使用,这里不做对比
  • DIMBIN

    • 针对多维数组设计的序列化方案,二进制存储,不需要IDL,自描述
    • 高性能,体积小,支持string、number、boolean