0%

avro序列化基本数据类型编码方式

avro序列化

  avro序列化后的编码有两种:二进制文本和JSON格式的数据。这里主要说的是二进制编码方式。

  avro有8种基本数据类型:

  • null: no value
  • boolean: a binary value
  • int: 32-bit signed integer
  • long: 64-bit signed integer
  • float: single precision(32-bit) IEEE 754 floating-point number
  • double: double precision(64-bit) IEEE 754 floating-point number
  • bytes: sequence of 8-bit unsigned bytes
  • string: unicode character sequence

##avro按照如下方式对这些基本类型进行二进制格式的序列化:

  • null 写0个字节(不写)

  • boolean 被写作一个值为0(false)或1(true)的单字节

  • intlong 按照变长整数和zig-zag编码
      变长整数(variable-length)格式的正整数表示方式如下:每个字节的左边第一位(小端编码)表示后边
    还有字节没有,去掉每隔字节的最高位剩下的位组织起来就是正整数的二进制表示。这样的话0-127就可以
    存放在1个字节中,128-16383
    可以存放在2个字节中,依次下去。比如:

值      第一个字节      第二个字节      第三个字节
0      00000000      
1       00000001
2       00000010

127     01111111
128     10000000      00000001
129     10000001      00000001      
130     10000001      00000001

16383   11111111      01111111
16384   10000000      10000000       00000001
16385   10000001      10000000       00000001

  但我们可以发现一个问题,变长整数现在只能表示正整数,如果直接用变长整数表示负数,负数会占用
所有的字节(singed int32_t占用32位,singed int64_t占用64位),这样并不利于压缩数据。这时候
zig-zag就派上用场了,它把带符号整数映射成无符号整数来减少负数的编码长度。。zig-zag字面意思是“之字形“、”相互交错“,其实它的用法也是如此,它在正整数和负整数之间交错,所以-1
编码成1,1编码成2,-2编码成3,如此,比如下表:
原始带符号整数        编码后
0                   0
-1                  1
1                   2
-2                  3
2147483647          4294967294
-2147483648         4294967295

换句话说,把n编码就是用如下公式:
(n << 1)^(n >> 31) //singed int32
(n << 1)^(n >> 63) //singed int64
注意第二个以为操作——(n >> 31)——是个算术右移,也就是说,结果不是全0(n是正整数)就是最后1位是1,其它位都是
0(n是负整数)的数字。反编码如下:
(n >> 1)^(n << 31) //singed int32
(n >> 1)^(n << 63) //singed int64

  • float编码成4字节,直接映射成int32类型的小端编码的4字节数字(IEEE754格式数字:
    31(最左):符号位;30-23:指数位;22-0:有效位/尾数)

  • double编码成8字节,直接映射成int64类型的小端编码的8字节数字(IEEE754格式数字:
    63(最左):符号位;62-52:指数位;51-0:有效位/尾数)

  • bytes编码成1个long类型数字n + n字节的数字

  • string 编码成1个long类型数字n + n字节UTF-8编码的数据.比如3个字节的”foo”会编码成
    3(十六进制为06)后跟UTF-8的编码’f’, ‘o’, ‘o’(十六进制分别为66 6f 6f):
    06 66 6f 6f

参考: