Apache Hive Protobuf SerDe
该项目用于 Hive 解析读取 Protobuf 序列化文件的一个组件.
因为项目的不确定性, 加字段是常见的. 因此需要对于加了字段不需要改 Schama, 或者改 Schama 还能不影响老数据是紧迫需求. 这种对于 Schama 和数据都不影响的方式存储数据, 可以用 JSON, AVRO,Protobuf 等. JSON 存储序列化和反序列化开销大, 并存储也比较大. Avro 目前并不流行, 当然 Hive 默认是对 Avro 支持的. 而我们的 Bean 都是 Protobuf 定义的, 因此开发 Hive-protobuf-serde 来支持 Hive 对 Protobuf 数据建表, 并查询.
序列化反序列化速度快, 序列化字节小, 增减字段对老数据兼容性好.
CREATE TABLE locations2 ( location STRING, locCountry BIGINT, locProvince BIGINT, locCity BIGINT, cityLevel INT) ROW FORMAT SERDE 'com.ivyft.hive.serde2.protobuf.ProtobufSerde' STORED AS INPUTFORMAT 'com.ivyft.hive.hadoop.IntLengthHeaderMr1InputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat' TBLPROPERTIES ('hive.protobuf.class' = 'com.ivyft.hive.serde2.entity.Entities$Location') SERDEPROPERTIES('hive.protobuf.class' = 'com.ivyft.hive.serde2.entity.Entities$Location') ;
该项目内部有一个IntLengthHeaderFile类, 内部的 Reader 和 Writer 可以读写 Protobuf 类. 写时的规则为:
byte[] bytes = protobufObject.toByteArray(); outputstream.writeInt(bytes.length); outputstream.write(bytes);
读时:
int length = inputstream.readInt(); byte[] bytes = new byte[length]; inputstream.read(bytes, 0, length); protobufObject = ProtobufClass.parseFrom(bytes);
用IntLengthHeaderFile类完全可以做到如上. 并能利用 Hive-Protobuf-Serde 解析.