Apache Avro 1.8.1 入门指南(Java)
2016-12-23 15:33
956 查看
在快速入门之前,我们先来了解一下Apache Avro到底是什么东东?能够用来做什么?
Apache Avro是一个数据序列化系统。序列化就是将对象转换成二进制流,相应的反序列化就是将二进制流再转换成对应的对象。因此,Avro就是用来在传输数据之前,将对象转换成二进制流,然后此二进制流达到目标地址后,Avro再将二进制流转换成对象。
接下来,我们看看官方网站上是怎么说的。
Apache Avro是一个数据序列化系统。
Avro提供:
丰富的数据结构
一个紧凑的,快速的,二进制的数据格式
一个容器文件,来存储持久化数据
远程过程调用(RPC)
简单的动态语言集成。
代码生成不需要读写数据文件,也不要使用或实现RPC协议。代码生成是作为一个可选的优化,只对静态类型的语言值得实现。
大家知道,JSON是一种轻量级的数据传输格式,对于大数据集,JSON数据会显示力不从心,因为JSON的格式是key:value型,每条记录都要附上key的名字,有的时候,光key消耗的空间甚至会超过value所占空间,这对空间的浪费十分严重,尤其是对大型数据集来说,因为它不仅不够紧凑,还要重复地加上key信息,不仅会造成存储空间上的浪费,更会增加了数据传输的压力,从而给集群增加负担,进而影响整个集群的吞吐量。而采用Avro数据序列化系统可以比较好的解决此问题,因为用Avro序列化后的文件由schema和真实内容组成,schema只是数据的元数据,相当于JSON数据的key信息,schema单独存放在一个JSON文件中,这样一来,数据的元数据只存了一次,相比JSON数据格式的文件,大大缩小了存储容量。从而使得Avro文件可以更加紧凑地组织数据。
接下来,我们开始使用Avro。
值得注意的是:以上pom文件配置了自动生成类的路径,即
然后在刚才配置的目录下就会生成相应的类,如下:
如果不使用插件,也可以使用avro-tools来生成:
这里,我们是序列化user到文件users.avro
整个创建avro schema,代码生成,创建用户,序列化用户对象,反序列化及最后的输出结果,完整的代码可以组织为以下(在这里,我使用的是JUNIT):
代码执行之后,可以发现,创建了文件users.avro。
输出结果为:
okay, 是不是很简单?
Apache Avro是一个数据序列化系统。序列化就是将对象转换成二进制流,相应的反序列化就是将二进制流再转换成对应的对象。因此,Avro就是用来在传输数据之前,将对象转换成二进制流,然后此二进制流达到目标地址后,Avro再将二进制流转换成对象。
接下来,我们看看官方网站上是怎么说的。
Apache Avro是一个数据序列化系统。
Avro提供:
丰富的数据结构
一个紧凑的,快速的,二进制的数据格式
一个容器文件,来存储持久化数据
远程过程调用(RPC)
简单的动态语言集成。
代码生成不需要读写数据文件,也不要使用或实现RPC协议。代码生成是作为一个可选的优化,只对静态类型的语言值得实现。
大家知道,JSON是一种轻量级的数据传输格式,对于大数据集,JSON数据会显示力不从心,因为JSON的格式是key:value型,每条记录都要附上key的名字,有的时候,光key消耗的空间甚至会超过value所占空间,这对空间的浪费十分严重,尤其是对大型数据集来说,因为它不仅不够紧凑,还要重复地加上key信息,不仅会造成存储空间上的浪费,更会增加了数据传输的压力,从而给集群增加负担,进而影响整个集群的吞吐量。而采用Avro数据序列化系统可以比较好的解决此问题,因为用Avro序列化后的文件由schema和真实内容组成,schema只是数据的元数据,相当于JSON数据的key信息,schema单独存放在一个JSON文件中,这样一来,数据的元数据只存了一次,相比JSON数据格式的文件,大大缩小了存储容量。从而使得Avro文件可以更加紧凑地组织数据。
接下来,我们开始使用Avro。
下载
以Maven为例,增加Avro的依赖,及插件,插件的好处在于,可以直接自动地为avsc文件生成类。<dependencies> <dependency> <groupId>org.apache.avro</groupId> <artifactId>avro</artifactId> <version>1.8.1</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.avro</groupId> <artifactId>avro-maven-plugin</artifactId> <version>1.8.1</version> <executions> <execution> <phase>generate-sources</phase> <goals> <goal>schema</goal> </goals> <configuration> <sourceDirectory>${project.basedir}/src/main/avro/</sourceDirectory> <outputDirectory>${project.basedir}/src/main/java/</outputDirectory> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> </plugins> </build>
值得注意的是:以上pom文件配置了自动生成类的路径,即
${project.basedir}/src/main/avro/和
${project.basedir}/src/main/java/,这样配置之后,在执行mvn命令的时候,这个插件就会自动将此目录下的avsc schema生成类文件,并放到后者这个目录下。
定义schema
使用JSON为Avro定义schema。schema由基本类型(null,boolean, int, long, float, double, bytes 和string)和复杂类型(record, enum, array, map, union, 和fixed)组成。例如,以下定义一个user的schema,在main目录下创建一个avro目录,然后在avro目录下新建文件 user.avsc :{"namespace": "lancoo.ecbdc.pre", "type": "record", "name": "User", "fields": [ {"name": "name", "type": "string"}, {"name": "favorite_number", "type": ["int", "null"]}, {"name": "favorite_color", "type": ["string", "null"]} ] }
用代码生成来序列化和反序列化
编译schema
在这里,因为使用avro插件,所以,直接输入以下命令,maven插件会自动帮我们生成类文件:mvn clean install
然后在刚才配置的目录下就会生成相应的类,如下:
如果不使用插件,也可以使用avro-tools来生成:
java -jar /path/to/avro-tools-1.8.1.jar compile schema <schema file> <destination>
创建用户
在前面,类文件已经创建好了,接下来,可以使用刚才自动生成的类来创建用户了:User user1 = new User(); user1.setName("Alyssa"); user1.setFavoriteNumber(256); // Leave favorite color null // Alternate constructor User user2 = new User("Ben", 7, "red"); // Construct via builder User user3 = User.newBuilder() .setName("Charlie") .setFavoriteColor("blue") .setFavoriteNumber(null) .build();
序列化
把前面创建的用户序列化并存储到磁盘文件:// 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();
这里,我们是序列化user到文件users.avro
反序列化
接下来,我们对序列化后的数据进行反序列化:// Deserialize Users from disk DatumReader<User> userDatumReader = new SpecificDatumReader<User>(User.class); DataFileReader<User> dataFileReader = new DataFileReader<User>(new File("users.avro"), 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); }
整个创建avro schema,代码生成,创建用户,序列化用户对象,反序列化及最后的输出结果,完整的代码可以组织为以下(在这里,我使用的是JUNIT):
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;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
/**
* Created by yang on 12/23/16.
*/
public class TestUser {
@Test
public void testCreateUserClass() throws IOException {
User user1 = new User(); user1.setName("Alyssa"); user1.setFavoriteNumber(256); // Leave favorite color null // Alternate constructor User user2 = new User("Ben", 7, "red"); // Construct via builder User user3 = User.newBuilder() .setName("Charlie") .setFavoriteColor("blue") .setFavoriteNumber(null) .build();
// 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>(new File("users.avro"), 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); }
}
}
代码执行之后,可以发现,创建了文件users.avro。
输出结果为:
{"name": "Alyssa", "favorite_number": 256, "favorite_color": null} {"name": "Ben", "favorite_number": 7, "favorite_color": "red"} {"name": "Charlie", "favorite_number": null, "favorite_color": "blue"}
okay, 是不是很简单?
相关文章推荐
- RPC failed; result=22, HTTP code = 411
- C#编程总结(一)序列化总结
- jquery.serialize() 函数语法及简单实例
- C#自定义序列化ISerializable的实现方法
- C# XML序列化方法及常用特性总结分析
- c#数据的序列化和反序列化(推荐版)
- PHP序列化操作方法分析
- mysql binlog二进制日志详解
- C语言二进制思想以及数据的存储
- 详解C++编程中对二进制文件的读写操作
- 整理C# 二进制,十进制,十六进制 互转
- c#序列化详解示例
- c#对象反序列化与对象序列化示例详解
- .net实现序列化与反序列化实例解析
- C#实现复杂XML的序列化与反序列化
- 在ASP.NET 2.0中操作数据之五十四:添加新记录时包含一个文件上传选项
- C#中Serializable序列化实例详解
- c#二进制逆序方法详解
- 浅析ES6的八进制与二进制整数字面量
- JS幻想 读取二进制文件第1/2页