Apache Avro入门实战

一、Avro简介

 

avro是一个数据序列化系统

Avro是Hadoop中的一个子项目,也是Apache中一个独立的项目,Avro是一个基于二进制数据传输高性能的中间件。在Hadoop的其他项目中例如HBase(Ref)和Hive(Ref)的Client端与服务端的数据传输也采用了这个工具。Avro是一个数据序列化的系统。Avro 可以将数据结构或对象转化成便于存储或传输的格式。Avro设计之初就用来支持数据密集型应用,适合于远程或本地大规模数据的存储和交换。

 

二、Schemas

 

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

 

所谓shemas,就是一种描述文件,能够说清楚对象的描述文件。如对象成员和属性,逻辑关系等。比如说对人的描述包括身高、体重等。

 

当把Avro数据存储到文件的时候,会把它的schema数据一起存储,这样数据就可以被接下来的任意程序使用了。

 

三、Avro的使用

 

1.下载相关JAR包

 

下载avro-1.8.2.jar和avro-tools-1.8.2.jar到指定的文件目录

(下载链接:http://mirror.bit.edu.cn/apache/avro/avro-1.8.2/

avro-tools.jar 将被用于代码生成

 

2.定义schema

如定义schema文件student.avsc

文件为Json格式:

{
	"type" : "record",
	"namespace" : "com.avro",
	"name" : "Student",
	"fields" : [
		{ "name" : "Name" , "type" : "string" },
		{ "name" : "age" , "type" : "int" }
	]
}

 

3. 通过编译方式进行序列化/反序列化

首先编译schema,生成java代码包

语法为:

java -jar /path/to/avro-tools-xxx.jar compile schema < schema file> < destination>

 

E:\work\avro>java -jar avro-tools-1.8.2.jar compile schema student.avsc .

可以看到根据Schema文件生成了一个代码包,里面有一个Student.java文件,将代码包直接导入项目src下。

注意:项目的包名称应与Schemas文件的namespace名称一致。

 

接着通过junit编写测试程序,序列化与反序列化代码如下:

public void write() throws Exception {
    //创建writer对象
    SpecificDatumWriter empDatumWriter = new SpecificDatumWriter<Student>(Student.class);
    //写入文件
    DataFileWriter<Student> empFileWriter = new DataFileWriter<Student>(empDatumWriter);

    //创建对象
    Student e1 = new Student();
    e1.setName("Susan");
    e1.setAge(19);

    Student e2 = new Student();
    e2.setName("james");
    e2.setAge(29);

    //串行化数据到磁盘
    empFileWriter.create(e1.getSchema(), new File("d:/avro/student.avro"));
    empFileWriter.append(e1);
    empFileWriter.append(e2);

    //关闭流
    empFileWriter.close();
}

@Test
public void read() throws Exception {
    //创建Reader对象
    SpecificDatumReader empDatumReader = new SpecificDatumReader<Student>(Student.class);
    //读取文件
    DataFileReader<Student> dataReader = new DataFileReader<Student>(new File("d:/avro/emp.avro")  ,empDatumReader);
    Iterator<Student> it = dataReader.iterator();
    while(it.hasNext()){
        Student emp = it.next();
        System.out.println(emp.getName()+" "+emp.getAge());
    }

    /*关闭流*/
    dataReader.close();
}

 

 

4.通过非编译方式进行序列化/反序列化

avro也可以不通过schemas文件编译生成代码,直接使用schemas

相关代码:

/**
 * 直接使用schema文件进行操作,不需要进行编译
 */
@Test
public void writeBySchema() throws  Exception {
    //指定定义的avsc文件。
    Schema schema = new Schema.Parser().parse(new File("d:/avro/student.avsc"));

    DatumWriter w1 = new SpecificDatumWriter (schema);
    DataFileWriter w2 = new DataFileWriter(w1);

    //创建GenericRecord,相当于Employee
    GenericRecord e1 = new GenericData.Record(schema);
    //设置javabean属性
    e1.put("Name", "mesi");
    e1.put("age", 25);

    GenericRecord e2 = new GenericData.Record(schema);
    //设置javabean属性
    e2.put("Name", "jack");
    e2.put("age", 26);

    w2.create(schema,new File("d:/avro/student2.avro")) ;
    w2.append(e1);
    w2.append(e2);

    w2.close();
}

/**
 * 反序列化读取avro数据
 */
@Test
public void readBySchema() throws  Exception {
    //指定定义的avsc文件。
    Schema schema = new Schema.Parser().parse(new File("d:/avro/student.avsc"));

    DatumReader r1 = new SpecificDatumReader (schema);
    DataFileReader r2 = new DataFileReader(new File("d:/avro/student2.avro"),r1);
    while(r2.hasNext()){
        GenericRecord rec = (GenericRecord)r2.next();
        System.out.println(rec.get("Name")+" "+rec.get("age"));
    }

    r2.close();
}

 

 

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Apache Avro是一个数据序列化系统,旨在支持快速、节省空间的数据交换和远程过程调用。它使用JSON格式定义数据结构,并支持动态类型,使其易于在不同编程语言之间进行交互。 使用Avro的步骤如下: 1. 定义数据结构:使用Avro的JSON格式定义数据结构,包括字段名、类型和默认值等信息。 例如,定义一个Person对象: ``` { "namespace": "example.avro", "type": "record", "name": "Person", "fields": [ {"name": "name", "type": "string"}, {"name": "age", "type": "int"} ] } ``` 2. 生成代码:使用Avro工具生成指定语言的代码,包括数据结构类和序列化/反序列化类等。 例如,使用Avro工具生成Java代码: ``` $ java -jar avro-tools-1.9.2.jar compile schema person.avsc . ``` 3. 序列化数据:使用生成的代码将数据序列化为字节数组。 例如,使用Java代码创建Person对象并序列化: ``` Person person = new Person("Alice", 30); ByteArrayOutputStream out = new ByteArrayOutputStream(); DatumWriter<Person> writer = new SpecificDatumWriter<Person>(Person.class); Encoder encoder = EncoderFactory.get().binaryEncoder(out, null); writer.write(person, encoder); encoder.flush(); byte[] bytes = out.toByteArray(); ``` 4. 反序列化数据:使用生成的代码将字节数组反序列化为数据对象。 例如,使用Java代码反序列化字节数组: ``` ByteArrayInputStream in = new ByteArrayInputStream(bytes); DatumReader<Person> reader = new SpecificDatumReader<Person>(Person.class); Decoder decoder = DecoderFactory.get().binaryDecoder(in, null); Person person2 = reader.read(null, decoder); ``` 这样,就完成了数据的序列化和反序列化。 以下是一个完整的Java代码示例: ``` import org.apache.avro.Schema; import org.apache.avro.Schema.Parser; import org.apache.avro.generic.GenericData; import org.apache.avro.generic.GenericRecord; import org.apache.avro.io.DatumReader; import org.apache.avro.io.DatumWriter; import org.apache.avro.io.Decoder; import org.apache.avro.io.DecoderFactory; import org.apache.avro.io.Encoder; import org.apache.avro.io.EncoderFactory; import org.apache.avro.specific.SpecificDatumReader; import org.apache.avro.specific.SpecificDatumWriter; import org.apache.avro.specific.SpecificRecord; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; public class AvroExample { public static void main(String[] args) throws IOException { // Define schema String schemaJson = "{\n" + " \"namespace\": \"example.avro\",\n" + " \"type\": \"record\",\n" + " \"name\": \"Person\",\n" + " \"fields\": [\n" + " {\"name\": \"name\", \"type\": \"string\"},\n" + " {\"name\": \"age\", \"type\": \"int\"}\n" + " ]\n" + "}"; Schema schema = new Parser().parse(schemaJson); // Serialize data Person person = new Person("Alice", 30); ByteArrayOutputStream out = new ByteArrayOutputStream(); DatumWriter<Person> writer = new SpecificDatumWriter<Person>(Person.class); Encoder encoder = EncoderFactory.get().binaryEncoder(out, null); writer.write(person, encoder); encoder.flush(); byte[] bytes = out.toByteArray(); // Deserialize data ByteArrayInputStream in = new ByteArrayInputStream(bytes); DatumReader<Person> reader = new SpecificDatumReader<Person>(Person.class); Decoder decoder = DecoderFactory.get().binaryDecoder(in, null); Person person2 = reader.read(null, decoder); System.out.println(person2.getName()); // Alice System.out.println(person2.getAge()); // 30 } public static class Person implements SpecificRecord { private String name; private int age; public Person() { } public Person(String name, int age) { this.name = name; this.age = age; } public void setName(String name) { this.name = name; } public String getName() { return name; } public void setAge(int age) { this.age = age; } public int getAge() { return age; } @Override public void put(int i, Object o) { } @Override public Object get(int i) { if (i == 0) { return name; } else if (i == 1) { return age; } return null; } @Override public Schema getSchema() { return null; } } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值