Avro介绍
Avro是一个数据序列化系统,设计用于支持大批量数据交换的应用。
它的主要特点有:支持二进制序列化方式,可以便捷,快速地处理大量数据;动态语言友好,Avro提供的机制使动态语言可以方便地处理Avro数据。
Avro 是Hadoop中的一个子项目,也是Apache中一个独立的项目,Avro是一个基于二进制数据传输高性能的中间件。在Hadoop的其他项目中例如HBase(Ref)和Hive(Ref)的Client端与服务端的数据传输也采用了这个工具,Avro可以做到将数据进行序列化,适用于远程或本地大批量数据交互。在传输的过程中Avro对数据二进制序列化后节约数据存储空间和网络传输带宽。 Avro支持本地和远程RPC(Ref)调用,RPC远程调用又分为Http和Netty2种.
特点:
1.丰富的数据结构类型
2.快速可压缩的二进制数据形式
3.存储持久数据的文件容器
4.远程过程调用(RPC)
5.同动态语言的简单集成。读写数据文件和使用RPC协议都不需要生成代码,而代码生成作为一种可选的优化只值得在静态类型语言中实现。
话不多说,进入正题,如何使用avro:
Avro应用
一、在pom.xml中添加依赖jar包
<dependency>
<groupId>org.apache.avro</groupId>
<artifactId>avro</artifactId> <!-- <2> -->
<version>1.8.2</version>
</dependency>
二、定义模式(Schema)
在avro中,它是用Json格式来定义模式的。模式可以由基础类型(null, boolean, int, long, float, double, bytes, and string)和复制类型(record, enum, array, map, union, and fixed)的数据组成。在模式定义中,必须包含它的类型(“type”: “record”)、一个名字(“name”: “RecordData”)以及fields (属性)
以 src\main\avro\record-data.avsc 为例 RecordData为我最终要传输的业务对象,里面有id,type,time等一系列属性,以下为record-data.avsc 模式文件内容
{
"namespace" : "com.xxx.timecat.elephant.avro",
"type": "record",
"name": "RecordData",
"fields": [{
"name": "id",
"type": ["null", "long"],
"default": null
}, {
"name": "type",
"type": ["null", "int"],
"default": null
}, {
"name": "time",
"type": ["null", "long"],
"default": null
}, {
"name": "relatedId",
"type": ["null", "string"],
"default": null
}, {
"name": "userId",
"type": ["null", "string"],
"default": null
}, {
"name": "pid",
"type": ["null", "string"],
"default": null
}, {
"name": "sessionId",
"type": ["null", "string"],
"default": null
}, {
"name": "tenantId",
"type": ["null", "string"],
"default": null
},{
"name": "data",
"type": ["null", "string"],
"default": null
}]
}
三、编译模式
我们用Avro Maven plugin方式来编辑
在pom.xml的<build><plugins>下添加如下plugin
<plugin>
<groupId>org.apache.avro</groupId>
<artifactId>avro-maven-plugin</artifactId>
<version>1.8.2</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>schema</goal>
</goals>
<configuration>
<sourceDirectory>src/main/avro</sourceDirectory> <!-- 模式(Schema)文件所在的地址 -->
<outputDirectory>${project.build.directory}/generated-sources</outputDirectory><!-- 根据以上模式生成的对象所在目录 -->
<stringType>String</stringType>
</configuration>
</execution>
</executions>
</plugin>
maven打包,会生成target\generated-sources\com\xxxx\timecat\elephant\avro\RecordData.java 文件
四、代码实例
我的业务是将RecordData.java对象放入消息队列中传输,直接使用即可,
以下是网上的一个例子,序列到文件,再序列化回来,可以参考
package cn.slimsmart.avro.demo;
import java.io.File;
import java.io.IOException;
import org.apache.avro.file.DataFileReader;
import org.apache.avro.file.DataFileWriter;
import org.apache.avro.io.DatumReader;
import org.apache.avro.io.DatumWriter;
import org.apache.avro.specific.SpecificDatumReader;
import org.apache.avro.specific.SpecificDatumWriter;
public class Test {
public static void main(String[] args) {
// 3种生成user对象的方法
User user1 = new User();
user1.setName("张山");
user1.setAge(23);
user1.setPhone("123456789");
User user2 = new User("李斯", 45, "987654321");
User user3 = User.newBuilder().setName("王二").setAge(57).setPhone("456893256").build();
// 序列化user到文件中
File file = new File("users.avro");
DatumWriter<User> userDatumWriter = new SpecificDatumWriter<User>(User.class);
DataFileWriter<User> dataFileWriter = new DataFileWriter<User>(userDatumWriter);
try {
dataFileWriter.create(user1.getSchema(), new File("src/main/avro/users.avro"));
dataFileWriter.append(user1);
dataFileWriter.append(user2);
dataFileWriter.append(user3);
dataFileWriter.flush();
dataFileWriter.close();
} catch (IOException e) {
}
// 从文件中反序列化对象
DatumReader<User> userDatumReader = new SpecificDatumReader<User>(User.class);
DataFileReader<User> dataFileReader = null;
try {
dataFileReader = new DataFileReader<User>(file, userDatumReader);
} catch (IOException e) {
}
User user = null;
try {
while (dataFileReader.hasNext()) {
user = dataFileReader.next(user);
System.out.println(user);
}
} catch (IOException e) {
}
}
}
官方示例:http://avro.apache.org/docs/current/gettingstartedjava.html