avro序列化
avro序列化后的编码有两种:二进制文本和JSON格式的数据。这里主要说的是二进制编码方式。
avro有8种基本数据类型:
null
: no valueboolean
: a binary valueint
: 32-bit signed integerlong
: 64-bit signed integerfloat
: single precision(32-bit) IEEE 754 floating-point numberdouble
: double precision(64-bit) IEEE 754 floating-point numberbytes
: sequence of 8-bit unsigned bytesstring
: unicode character sequence
##avro按照如下方式对这些基本类型进行二进制格式的序列化:
null
写0个字节(不写)boolean
被写作一个值为0(false)或1(true)的单字节int
或long
按照变长整数和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
参考: