【Hadoop】数据序列化系统Avro

  • Avro简介

    • schema
  • 文件组成
    • Header与Datablock声明代码
    • 测试代码
  • 序列化与反序列化
    • specific
    • generic
  • 参考资料

Avro简介

Avro是由Doug Cutting(Hadoop之父)创建的数据序列化系统,旨在解决Writeable类型的不足:缺乏语言的可移植性。为了支持跨语言,Avro的schema与语言的模式无关。有关Avro的更多特性请参看官方文档 1。

Avro文件的读写是依据schema而进行的。通常情况下,Avro的schema是用JSON编写,而数据部分则是二进制格式编码,并采用压缩算法对数据进行压缩,以便减少传输量。

schema

schema中数据字段的类型包括两种

  • 原生类型(primitive types): null, boolean, int, long, float, double, bytes, and string
  • 复杂类型(complex types): record, enum, array, map, union, and fixed

复杂类型比较常用的record。这里用[2]中twitter.avro文件为例,打开文件后,文件头如下:

Objavro.codecnullavro.schemaò{“type”:”record”,”name”:”twitter_schema”,”namespace”:”com.miguno.avro”,”fields”:[{“name”:”username”,”type”:”string”,”doc”:”Name of the user account on Twitter.com”},{“name”:”tweet”,”type”:”string”,”doc”:”The content of the user’s Twitter message”},{“name”:”timestamp”,”type”:”long”,”doc”:”Unix epoch time in milliseconds”}],”doc:”:”A basic schema for storing Twitter messages”}

将schema格式化之后

{
    "type": "record",
    "name": "twitter_schema",
    "namespace": "com.miguno.avro",
    "fields": [
        {
            "name": "username", "type": "string",
            "doc": "Name of the user account on Twitter.com"
        },
        {
            "name": "tweet", "type": "string",
            "doc": "The content of the user‘s Twitter message"
        },
        {
            "name": "timestamp", "type": "long",
            "doc": "Unix epoch time in milliseconds"
        }
    ],
    "doc:": "A basic schema fostoring Twitter messages"
}

其中,name是该JSON串的名字,type是指明name的类型,doc是对该name更为详细的说明。

文件组成

3中的图对Avro文件进行详细地描述,一个文件由header与多个data block组成。header主要由MetaDatas与16位sync marker组成,MetaDatas中的信息包含codec与schema;codec是data block中的数据采用的压缩方式,为null(不压缩)或者是deflate。deflate算法是gzip所采用的压缩算法,就我自己感觉而言压缩比在6倍以上(具体还没研究过)。

其实每个data block间都会间隔一个sync marker,具体参看4。sync marker是为了用于mapReduce阶段时文件分割与同步;此外Avro本身是为了mapReduce而设计的。

Header与Datablock声明代码

//org.apache.avro.file.DataFileStream.java

  public static final class Header {
    Schema schema;
    Map<String,byte[]> meta = new HashMap<String,byte[]>();
    private transient List<String> metaKeyList = new ArrayList<String>();
    byte[] sync = new byte[DataFileConstants.SYNC_SIZE]; //byte[16]
    private Header() {}
  }

  static class DataBlock {
    private byte[] data;
    private long numEntries;
    private int blockSize;
    private int offset = 0;
    private boolean flushOnWrite = true;
    private DataBlock(long numEntries, int blockSize) {
      this.data = new byte[blockSize];
      this.numEntries = numEntries;
      this.blockSize = blockSize;
    }

测试代码

DataFileReader<Void> reader =
                  new DataFileReader<Void>(new FsInput(new Path("twitter.avro"), new Configuration()),
                                           new GenericDatumReader<Void>());
//print schema
System.out.println(reader.getSchema().toString(true));

//print meta
List<String> metaKeyList = reader.getMetaKeys();
System.out.println(metaKeyList.toString());
System.out.println(reader.getMetaString("avro.codec"));
System.out.println(reader.getMetaString("avro.schema"));

//print blockount
reader.getBlockCount();

//print the data in data block
System.out.println(reader.next());

可以看到meta中存放的是avro.codec, avro.schema。

序列化与反序列化

官网上给出了两种序列化方式:specific与generic。

specific

// Serialize user1, user2 and user3 to disk
DatumWriter<User> userDatumWriter = new SpecificDatumWriter<User>(User.class);
DataFileWriter<User> dataFileWriter = new DataFileWriter<User>(userDatumWriter);
dataFileWriter.create(user1.getSchema(), new File("users.avro"));
dataFileWriter.append(user1);
dataFileWriter.append(user2);
dataFileWriter.append(user3);
dataFileWriter.close();

// Deserialize Users from disk
DatumReader<User> userDatumReader = new SpecificDatumReader<User>(User.class);
DataFileReader<User> dataFileReader = new DataFileReader<User>(file, userDatumReader);
User user = null;
while (dataFileReader.hasNext()) {
// Reuse user object by passing it to next(). This saves us from
// allocating and garbage collecting many objects for files with
// many items.
user = dataFileReader.next(user);
System.out.println(user);
}

specific的方式是根据所生成的User类,提取出schema来进行Avro的解析。

generic

GenericRecord user1 = new GenericData.Record(schema);
user1.put("name", "Alyssa");
user1.put("favorite_number", 256);
// Leave favorite color null

GenericRecord user2 = new GenericData.Record(schema);
user2.put("name", "Ben");
user2.put("favorite_number", 7);
user2.put("favorite_color", "red");

// Serialize user1 and user2 to disk
File file = new File("users.avro");
DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<GenericRecord>(schema);
DataFileWriter<GenericRecord> dataFileWriter = new DataFileWriter<GenericRecord>(datumWriter);
dataFileWriter.create(schema, file);
dataFileWriter.append(user1);
dataFileWriter.append(user2);
dataFileWriter.close();

generic的方式是预先生成了一个schema,然后再根据其解析。因为Avro文件会将schema写在文件头,所以在平常做解析时,generic的方式更为常见。

avro-tools的jar包提供了对Avro文件丰富的操作,包括对Avro文件进行切割,以用于做测试数据。

Available tools:
      compile  Generates Java code for the given schema.
       concat  Concatenates avro files without re-compressing.
   fragtojson  Renders a binary-encoded Avro datum as JSON.
     fromjson  Reads JSON records and writes an Avro data file.
     fromtext  Imports a text file into an avro data file.
      getmeta  Prints out the metadata of an Avro data file.
    getschema  Prints out schema of an Avro data file.
          idl  Generates a JSON schema from an Avro IDL file
       induce  Induce schema/protocol from Java class/interface via reflection.
   jsontofrag  Renders a JSON-encoded Avro datum as binary.
      recodec  Alters the codec of a data file.
  rpcprotocol  Output the protocol of a RPC service
   rpcreceive  Opens an RPC Server and listens for one message.
      rpcsend  Sends a single RPC message.
       tether  Run a tethered mapreduce job.
       tojson  Dumps an Avro data file as JSON, one record per line.
       totext  Converts an Avro data file to a text file.
  trevni_meta  Dumps a Trevni file‘s metadata as JSON.
trevni_random  Create a Trevni file filled with random instances of a schema.
trevni_tojson  Dumps a Trevni file as JSON.

参考资料


  1. Apache Avro documentation. ?
  2. miguno, avro-cli-examples. ?
  3. xyw_Eliot, Avro简介. ?
  4. guibin, AVRO文件结构分析. ?

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2025-01-12 15:17:24

【Hadoop】数据序列化系统Avro的相关文章

Avro数据序列化

序列化:把结构化的对象转换成字节流,使得能够在系统中或网络中通信 需要把数据存储到hadoop的hbase 常用序列化系统 thrift   (hive,hbase) Protocol Buffer (google) avro

细水长流话Hadoop(1)Hadoop序列化系统

声明:个人原创,转载请注明出处.文中引用了一些网上或书里的资料,如有不妥之处请告之. 本文是我阅读Hadoop 0.20.2第二遍时写的笔记,在阅读过程中碰到很多问题,最终通过各种途径解决了大部分.Hadoop整个系统设计精良,源码值得学习分布式的同学们阅读,以后会将所有笔记一一贴出,希望能方便大家阅读Hadoop源码,少走弯路. 1 序列化核心技术... 1 2 类型对象大小比较... 3 3 Writable类型工厂... 4 4 ObjectWritable类型... 5 5 其它序列化系

大数据框架hadoop的序列化机制

Java内建序列化机制 在Windows系统上序列化的Java对象,可以在UNIX系统上被重建出来,不需要担心不同机器上的数据表示方法,也不需要担心字节排列次序. 在Java中,使一个类的实例可被序列化非常简单,只需要在类声明中加入implements Serializable即可.Serializable接口是一个标志,不具有任何成员函数,其定义如下: public interface Serializable { } Block类通过声明它实现了Serializable 接口,立即可以获得J

Hadoop数据收集与入库系统Flume与Sqoop

Hadoop提供了一个中央化的存储系统,其有利于进行集中式的数据分析与数据共享. Hadoop对存储格式没有要求.可以存储用户访问日志.产品信息以及网页数据等数据. 常见的两种数据来源.一种是分散的数据源:机器产生的数据.用户访问日志以及用户购买日志.另一种是传统系统中的数据:传统关系型数据库(MySQL.Oracle).磁盘阵列以及磁带. Flume由三部分构成.Master负责负责通信及配置管理,是集群的控制器.Collector用于对数据进行聚合.往往会产生一个更大的数据流.然后加载到HD

java序列化与反序列化以及浅谈一下hadoop的序列化

1.什么是序列化和反序列化 神马是序列化呢,序列化就是把内存中的对象的状态信息,转换成字节序列以便于存储(持久化)和网络传输.(网络传输和硬盘持久化,你没有一定的手段来进行辨别这些字节序列是什么东西,有什么信息,这些字节序列就是垃圾). 反序列化就是将收到字节序列或者是硬盘的持久化数据,转换成内存中的对象. 2.JDK的序列化 JDK的序列化只有实现了serializable接口就能实现序列化与反序列化,但是记得一定要加上序列化版本ID serialVersionUID 这个是识别序列化的之前那

(转)Memcache,Redis,MongoDB(数据缓存系统)方案对比与分析

Memcache,Redis,MongoDB(数据缓存系统)方案对比与分析 数据库表数据量极大(千万条),要求让服务器更加快速地响应用户的需求. 二.解决方案: 1.通过高速服务器Cache缓存数据库数据 2.内存数据库 (这里仅从数据缓存方面考虑,当然,后期可以采用Hadoop+HBase+Hive等分布式存储分析平台) 三.主流解Cache和数据库对比: 上述技术基本上代表了当今在数据存储方面所有的实现方案,其中主要涉及到了普通关系型数据库(MySQL/PostgreSQL),NoSQL数据

jQuery源码解读 - 数据缓存系统:jQuery.data

jQuery在1.2后引入jQuery.data(数据缓存系统),主要的作用是让一组自定义的数据可以DOM元素相关联——浅显的说:就是让一个对象和一组数据一对一的关联. 一组和Element相关的数据如何关联着这个Element一直是web前端的大姨妈,而最初的jQuery事件系统照搬Dean Edwards的addEvent.js:将回调挂载在EventTarget上,这样下来,循环引用是不可忽视的问题.而在web前端中,数据和DOM的关系太过基情和紧张,于是jQuery在1.2中,正式缔造了

大数据培训&lt;一&gt; Avro

由于最近在整理公司的培训事情,首先培训的就是Avro,故这里做一个记录 一.介绍,直接看官网来得快 官方网站:http://avro.apache.org/ 1.1.Maven项目构建pom示例 所需要的jar包  <!-- 测试类 -->              <dependency>                    <groupId> junit</groupId >                    <artifactId> 

大数据云计算系统顶级架构培训视频教程

38套大数据,云计算,架构,数据分析师,Hadoop,Spark,Storm,Kafka,人工智能,机器学习,深度学习,项目实战视频教程 视频课程包含: 38套大数据和人工智能精品高级课包含:大数据,云计算,架构,数据挖掘实战,实时推荐系统实战,电视收视率项目实战,实时流统计项目实战,离线电商分析项目实战,Spark大型项目实战用户分析,智能客户系统项目实战,Linux基础,Hadoop,Spark,Storm,Docker,Mapreduce,Kafka,Flume,OpenStack,Hiv