一、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.class);
//写入文件
DataFileWriter empFileWriter = new DataFileWriter(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.class);
//读取文件
DataFileReader dataReader = new DataFileReader(new File("d:/avro/emp.avro") ,empDatumReader);
Iterator 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();
}