美文网首页
数据格式--二进制格式

数据格式--二进制格式

作者: MontyOak | 来源:发表于2018-01-28 22:44 被阅读10次

    Thrift与Protocol Buffers

    在大量调用或者需要传输大量数据的时候,数据编码之后的体积大小就是一个尤为关键的因素。Apache ThriftProtocol Buffers(protobuf)就是业界最为知名的两种二进制编码格式。其中前者由Facebook发起并贡献给了Apache作为开源项目,后者则有Google发起并开源。两者格式有很多相似之处,一般都是作为接口定义语言(IDL)配合RPC传输协议使用。

    # 一个thrift例子
    struct Person {
      1: required string userName,
      2: optional i64 favoriteNumber,
      3: optional list<string> interests
    }
    
    # 一个protobuf例子
    message Person {
      required string user_name = 1;
      optional int64 favorite_number = 2;
      repeated string interests = 3;
    }
    

    相比之前提到的JSON格式,这两者最大的优势在于编码时避免使用完整键的值,而是使用域标签作为键(通常是1,2,3这样的整形数字)。在Thrift和protobuf里,域标签就代表一个字段,而不用完整的键来代表一个字段。
    需要提到的一点是,在字段标示属性由一个optional或者required字段。这个属性表明该字段是否是必填,required的校验是在运行时做的,编码时这两种属性并没有实质差异。

    来看一下,thrift和protobuf是怎么处理向前兼容和向后兼容的。就像上面说的,字段是和域标签一对一绑定的。也就是说字段名可以变换,而对于同一字段的域标签则要保持不变。当需要添加新字段时,将新的域标签绑定到新字段上即可。对于旧代码读取新数据的情况,未被代码端标示的字段将被自动抛弃而不影响其他字段的读取,由此可见,向前兼容可以被轻松实现。
    由于域标签在struct层级保持唯一,新代码可以轻松按照域标签读取旧数据。需要注意的一点是,新添加的字段不能被标记成required,否则在新代码读取旧数据时发生字段缺少的问题。同样的,删除字段时也应该只删除optional字段。域标签和字段的绑定关系应该保持不变,不能用新的字段绑定旧的域标签。
    更换字段的数据类型不会发生报错,但是可以会出现精度损失或者溢出的情况(旧代码端的i32读取新数据模式的i64可能会出现溢出情况,旧代码的i32读取新数据模式的float则会出现精度损失)。

    Avro

    Apache Avro是另一种二进制数据格式。它是Hadoop项目的一个子项,致力于解决HDFS内的数据传输。
    Avro允许读写两种数据模式的存在。读写两种模式之间的字段按照字段名进行匹配。

    相比JSON和XML,二进制数据格式有下面这些优点:

    • 编码之后拥有更小的数据体积(因为采用域标签来代替完整的域的值)
    • 数据声明本身就可以当做是接口文档使用,而且保证是线上运行的最新版本。
    • 对于静态语言而言,在编译时做类型检查的特性可以规避很多问题。

    相关文章

      网友评论

          本文标题:数据格式--二进制格式

          本文链接:https://www.haomeiwen.com/subject/agxtzxtx.html